Merge "Use readUnsignedByte."
diff --git a/Android.mk b/Android.mk
index 294a2fe..462d6ac 100644
--- a/Android.mk
+++ b/Android.mk
@@ -166,6 +166,7 @@
core/java/android/speech/IRecognitionService.aidl \
core/java/android/speech/tts/ITextToSpeechCallback.aidl \
core/java/android/speech/tts/ITextToSpeechService.aidl \
+ core/java/com/android/internal/app/IAppOpsService.aidl \
core/java/com/android/internal/app/IBatteryStats.aidl \
core/java/com/android/internal/app/IUsageStats.aidl \
core/java/com/android/internal/app/IMediaContainerService.aidl \
diff --git a/api/current.txt b/api/current.txt
index e4d5fd1..72e7601 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13785,12 +13785,18 @@
method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
method public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...);
method public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
+ field public static final java.lang.String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
field public static final java.lang.String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
field public static final java.lang.String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
field public static final java.lang.String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
+ field public static final java.lang.String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE";
field public static final java.lang.String EXTRA_ID = "android.nfc.extra.ID";
field public static final java.lang.String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
field public static final java.lang.String EXTRA_TAG = "android.nfc.extra.TAG";
+ field public static final int STATE_OFF = 1; // 0x1
+ field public static final int STATE_ON = 3; // 0x3
+ field public static final int STATE_TURNING_OFF = 4; // 0x4
+ field public static final int STATE_TURNING_ON = 2; // 0x2
}
public static abstract interface NfcAdapter.CreateBeamUrisCallback {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 3bdadc3..d6ddeb6 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2844,7 +2844,7 @@
* item has been selected.
* <p>
* It is not safe to hold onto the context menu after this method returns.
- * {@inheritDoc}
+ *
*/
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
new file mode 100644
index 0000000..7210df4
--- /dev/null
+++ b/core/java/android/app/AppOpsManager.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import com.android.internal.app.IAppOpsService;
+
+import android.content.Context;
+import android.os.Process;
+import android.os.RemoteException;
+
+/** @hide */
+public class AppOpsManager {
+ final Context mContext;
+ final IAppOpsService mService;
+
+ public static final int MODE_ALLOWED = 0;
+ public static final int MODE_IGNORED = 1;
+ public static final int MODE_ERRORED = 2;
+
+ public static final int OP_LOCATION = 0;
+ public static final int OP_GPS = 1;
+ public static final int OP_VIBRATE = 2;
+
+ public static String opToString(int op) {
+ switch (op) {
+ case OP_LOCATION: return "LOCATION";
+ case OP_GPS: return "GPS";
+ case OP_VIBRATE: return "VIBRATE";
+ default: return "Unknown(" + op + ")";
+ }
+ }
+
+ public AppOpsManager(Context context, IAppOpsService service) {
+ mContext = context;
+ mService = service;
+ }
+
+ public int noteOp(int op, int uid, String packageName) {
+ try {
+ int mode = mService.noteOperation(op, uid, packageName);
+ if (mode == MODE_ERRORED) {
+ throw new SecurityException("Operation not allowed");
+ }
+ return mode;
+ } catch (RemoteException e) {
+ }
+ return MODE_IGNORED;
+ }
+
+ public int noteOpNoThrow(int op, int uid, String packageName) {
+ try {
+ return mService.noteOperation(op, uid, packageName);
+ } catch (RemoteException e) {
+ }
+ return MODE_IGNORED;
+ }
+
+ public int noteOp(int op) {
+ return noteOp(op, Process.myUid(), mContext.getPackageName());
+ }
+
+ public int startOp(int op, int uid, String packageName) {
+ try {
+ int mode = mService.startOperation(op, uid, packageName);
+ if (mode == MODE_ERRORED) {
+ throw new SecurityException("Operation not allowed");
+ }
+ return mode;
+ } catch (RemoteException e) {
+ }
+ return MODE_IGNORED;
+ }
+
+ public int startOpNoThrow(int op, int uid, String packageName) {
+ try {
+ return mService.startOperation(op, uid, packageName);
+ } catch (RemoteException e) {
+ }
+ return MODE_IGNORED;
+ }
+
+ public int startOp(int op) {
+ return startOp(op, Process.myUid(), mContext.getPackageName());
+ }
+
+ public void finishOp(int op, int uid, String packageName) {
+ try {
+ mService.finishOperation(op, uid, packageName);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void finishOp(int op) {
+ finishOp(op, Process.myUid(), mContext.getPackageName());
+ }
+}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 7431765..03d1a3f 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -142,6 +142,21 @@
}
@Override
+ public int getPackageUid(String packageName, int userHandle)
+ throws NameNotFoundException {
+ try {
+ int uid = mPM.getPackageUid(packageName, userHandle);
+ if (uid >= 0) {
+ return uid;
+ }
+ } catch (RemoteException e) {
+ throw new RuntimeException("Package manager has died", e);
+ }
+
+ throw new NameNotFoundException(packageName);
+ }
+
+ @Override
public PermissionInfo getPermissionInfo(String name, int flags)
throws NameNotFoundException {
try {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index f895ccc..8ef708c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -47,11 +47,9 @@
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.hardware.ISerialManager;
-import android.hardware.SensorManager;
import android.hardware.SerialManager;
import android.hardware.SystemSensorManager;
import android.hardware.display.DisplayManager;
-import android.hardware.input.IInputManager;
import android.hardware.input.InputManager;
import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbManager;
@@ -109,6 +107,8 @@
import android.accounts.AccountManager;
import android.accounts.IAccountManager;
import android.app.admin.DevicePolicyManager;
+
+import com.android.internal.app.IAppOpsService;
import com.android.internal.os.IDropBoxManagerService;
import java.io.File;
@@ -499,7 +499,7 @@
registerService(VIBRATOR_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
- return new SystemVibrator();
+ return new SystemVibrator(ctx);
}});
registerService(WALLPAPER_SERVICE, WALLPAPER_FETCHER);
@@ -530,11 +530,18 @@
}});
registerService(USER_SERVICE, new ServiceFetcher() {
- public Object getService(ContextImpl ctx) {
+ public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(USER_SERVICE);
IUserManager service = IUserManager.Stub.asInterface(b);
return new UserManager(ctx, service);
}});
+
+ registerService(APP_OPS_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
+ IBinder b = ServiceManager.getService(APP_OPS_SERVICE);
+ IAppOpsService service = IAppOpsService.Stub.asInterface(b);
+ return new AppOpsManager(ctx, service);
+ }});
}
static ContextImpl getImpl(Context context) {
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 9c19766..6b1c3e2 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -239,7 +239,7 @@
public static final String EXTRA_CUSTOM_SORT = "customSort";
/**
- * A sentiel value that the AppWidget manager will never return as a appWidgetId.
+ * A sentinel value that the AppWidget manager will never return as a appWidgetId.
*/
public static final int INVALID_APPWIDGET_ID = 0;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 257f84e..41d470b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -64,44 +64,30 @@
*/
public static final int MODE_PRIVATE = 0x0000;
/**
+ * @deprecated Creating world-readable files is very dangerous, and likely
+ * to cause security holes in applications. It is strongly discouraged;
+ * instead, applications should use more formal mechanism for interactions
+ * such as {@link ContentProvider}, {@link BroadcastReceiver}, and
+ * {@link android.app.Service}. There are no guarantees that this
+ * access mode will remain on a file, such as when it goes through a
+ * backup and restore.
* File creation mode: allow all other applications to have read access
* to the created file.
- *
- * <b>Note:</b> Applications with {@code targetSdkVersion}
- * {@link android.os.Build.VERSION_CODES#K} or greater have home directories
- * with {@code 0700} permissions. Because an application's home directory
- * is no longer world-accessible, world-readable files created within the
- * application's home directory will not be accessible to other applications.
- *
- * @deprecated Creating world-readable files is very dangerous, and likely
- * to cause security holes in applications. It is strongly discouraged;
- * instead, applications should use more formal mechanism for interactions
- * such as {@link ContentProvider}, {@link BroadcastReceiver}, and
- * {@link android.app.Service}. There are no guarantees that this
- * access mode will remain on a file, such as when it goes through a
- * backup and restore.
* @see #MODE_PRIVATE
* @see #MODE_WORLD_WRITEABLE
*/
@Deprecated
public static final int MODE_WORLD_READABLE = 0x0001;
/**
+ * @deprecated Creating world-writable files is very dangerous, and likely
+ * to cause security holes in applications. It is strongly discouraged;
+ * instead, applications should use more formal mechanism for interactions
+ * such as {@link ContentProvider}, {@link BroadcastReceiver}, and
+ * {@link android.app.Service}. There are no guarantees that this
+ * access mode will remain on a file, such as when it goes through a
+ * backup and restore.
* File creation mode: allow all other applications to have write access
* to the created file.
- *
- * <b>Note:</b> Applications with {@code targetSdkVersion}
- * {@link android.os.Build.VERSION_CODES#K} or greater have home directories
- * with {@code 0700} permissions. Because an application's home directory
- * is no longer world-accessible, world-writable files created within the
- * application's home directory will not be accessible to other applications.
- *
- * @deprecated Creating world-writable files is very dangerous, and likely
- * to cause security holes in applications. It is strongly discouraged;
- * instead, applications should use more formal mechanism for interactions
- * such as {@link ContentProvider}, {@link BroadcastReceiver}, and
- * {@link android.app.Service}. There are no guarantees that this
- * access mode will remain on a file, such as when it goes through a
- * backup and restore.
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
*/
@@ -515,22 +501,18 @@
throws FileNotFoundException;
/**
- * Open a file associated with this Context's application package
+ * Open a private file associated with this Context's application package
* for writing. Creates the file if it doesn't already exist.
*
- * <b>Note:</b> Applications with {@code targetSdkVersion}
- * {@link android.os.Build.VERSION_CODES#K} or greater have home directories
- * with {@code 0700} permissions. Because an application's home directory
- * is no longer world-accessible, files created with {@code mode}
- * {@link #MODE_WORLD_READABLE} or {@link #MODE_WORLD_WRITEABLE} will not be
- * accessible to other applications.
- *
- * @param name The name of the file to open; can not contain path separators.
+ * @param name The name of the file to open; can not contain path
+ * separators.
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
- * default operation, {@link #MODE_APPEND} to append to an existing file,
- * {@link #MODE_WORLD_READABLE} and {@link #MODE_WORLD_WRITEABLE} to control
- * permissions.
+ * default operation, {@link #MODE_APPEND} to append to an existing file,
+ * {@link #MODE_WORLD_READABLE} and {@link #MODE_WORLD_WRITEABLE} to control
+ * permissions.
+ *
* @return FileOutputStream Resulting output stream.
+ *
* @see #MODE_APPEND
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
@@ -756,19 +738,14 @@
* application; you can only set the mode of the entire directory, not
* of individual files.
*
- * <b>Note:</b> Applications with {@code targetSdkVersion}
- * {@link android.os.Build.VERSION_CODES#K} or greater have home directories
- * with {@code 0700} permissions. Because an application's home directory
- * is no longer world-accessible, world-readable / world-writable directories
- * created using this method will not be accessible to other applications.
- *
* @param name Name of the directory to retrieve. This is a directory
- * that is created as part of your application data.
+ * that is created as part of your application data.
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
- * default operation, {@link #MODE_WORLD_READABLE} and
- * {@link #MODE_WORLD_WRITEABLE} to control permissions.
+ * default operation, {@link #MODE_WORLD_READABLE} and
+ * {@link #MODE_WORLD_WRITEABLE} to control permissions.
+ *
* @return Returns a File object for the requested directory. The directory
- * will have been created if it does not already exist.
+ * will have been created if it does not already exist.
*
* @see #openFileOutput(String, int)
*/
@@ -778,13 +755,6 @@
* Open a new private SQLiteDatabase associated with this Context's
* application package. Create the database file if it doesn't exist.
*
- * <b>Note:</b> Applications with {@code targetSdkVersion}
- * {@link android.os.Build.VERSION_CODES#K} or greater have home directories
- * with {@code 0700} permissions. Because an application's home directory
- * is no longer world-accessible, {@code SQLiteDatabase}s created with {@code mode}
- * {@link #MODE_WORLD_READABLE} or {@link #MODE_WORLD_WRITEABLE} will not be
- * accessible to other applications.
- *
* @param name The name (unique in the application package) of the database.
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
* default operation, {@link #MODE_WORLD_READABLE}
@@ -792,8 +762,10 @@
* Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
* @param factory An optional factory class that is called to instantiate a
* cursor when query is called.
+ *
* @return The contents of a newly created database with the given name.
* @throws android.database.sqlite.SQLiteException if the database file could not be opened.
+ *
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
* @see #MODE_WORLD_WRITEABLE
@@ -810,13 +782,6 @@
* <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
* used to handle corruption when sqlite reports database corruption.</p>
*
- * <b>Note:</b> Applications with {@code targetSdkVersion}
- * {@link android.os.Build.VERSION_CODES#K} or greater have home directories
- * with {@code 0700} permissions. Because an application's home directory
- * is no longer world-accessible, {@code SQLiteDatabase}s created with {@code mode}
- * {@link #MODE_WORLD_READABLE} or {@link #MODE_WORLD_WRITEABLE} will not be
- * accessible to other applications.
- *
* @param name The name (unique in the application package) of the database.
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
* default operation, {@link #MODE_WORLD_READABLE}
@@ -825,9 +790,10 @@
* @param factory An optional factory class that is called to instantiate a
* cursor when query is called.
* @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
- * corruption. if null, {@link android.database.DefaultDatabaseErrorHandler} is assumed.
+ * corruption. if null, {@link android.database.DefaultDatabaseErrorHandler} is assumed.
* @return The contents of a newly created database with the given name.
* @throws android.database.sqlite.SQLiteException if the database file could not be opened.
+ *
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
* @see #MODE_WORLD_WRITEABLE
@@ -2289,6 +2255,18 @@
public static final String USER_SERVICE = "user";
/**
+ * Use with {@link #getSystemService} to retrieve a
+ * {@link android.app.AppOpsManager} for tracking application operations
+ * on the device.
+ *
+ * @see #getSystemService
+ * @see android.app.AppOpsManager
+ *
+ * @hide
+ */
+ public static final String APP_OPS_SERVICE = "appops";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 8ba1988..cdd9195 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1280,6 +1280,22 @@
throws NameNotFoundException;
/**
+ * @hide Return the uid associated with the given package name for the
+ * given user.
+ *
+ * <p>Throws {@link NameNotFoundException} if a package with the given
+ * name can not be found on the system.
+ *
+ * @param packageName The full name (i.e. com.google.apps.contacts) of the
+ * desired package.
+ * @param userHandle The user handle identifier to look up the package under.
+ *
+ * @return Returns an integer uid who owns the given package name.
+ */
+ public abstract int getPackageUid(String packageName, int userHandle)
+ throws NameNotFoundException;
+
+ /**
* Retrieve all of the information we know about a particular permission.
*
* <p>Throws {@link NameNotFoundException} if a permission with the given
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 4baceed..6ad382b 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -174,31 +174,25 @@
* Broadcast Action: The state of the local NFC adapter has been
* changed.
* <p>For example, NFC has been turned on or off.
- * <p>Always contains the extra field {@link #EXTRA_STATE}
- * @hide
+ * <p>Always contains the extra field {@link #EXTRA_ADAPTER_STATE}
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ADAPTER_STATE_CHANGED =
"android.nfc.action.ADAPTER_STATE_CHANGED";
/**
- * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
+ * Used as an int extra field in {@link #ACTION_ADAPTER_STATE_CHANGED}
* intents to request the current power state. Possible values are:
* {@link #STATE_OFF},
* {@link #STATE_TURNING_ON},
* {@link #STATE_ON},
* {@link #STATE_TURNING_OFF},
- * @hide
*/
public static final String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE";
- /** @hide */
public static final int STATE_OFF = 1;
- /** @hide */
public static final int STATE_TURNING_ON = 2;
- /** @hide */
public static final int STATE_ON = 3;
- /** @hide */
public static final int STATE_TURNING_OFF = 4;
/** @hide */
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9821824..abbb6a1 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -93,6 +93,11 @@
public static final int VIDEO_TURNED_ON = 8;
/**
+ * A constant indicating a vibrator on timer
+ */
+ public static final int VIBRATOR_ON = 9;
+
+ /**
* Include all of the data in the stats, including previously saved data.
*/
public static final int STATS_SINCE_CHARGED = 0;
@@ -131,6 +136,7 @@
private static final String APK_DATA = "apk";
private static final String PROCESS_DATA = "pr";
private static final String SENSOR_DATA = "sr";
+ private static final String VIBRATOR_DATA = "vib";
private static final String WAKELOCK_DATA = "wl";
private static final String KERNEL_WAKELOCK_DATA = "kwl";
private static final String NETWORK_DATA = "nt";
@@ -277,6 +283,7 @@
int which);
public abstract long getAudioTurnedOnTime(long batteryRealtime, int which);
public abstract long getVideoTurnedOnTime(long batteryRealtime, int which);
+ public abstract Timer getVibratorOnTimer();
/**
* Note that these must match the constants in android.os.PowerManager.
@@ -1395,6 +1402,16 @@
}
}
+ Timer vibTimer = u.getVibratorOnTimer();
+ if (vibTimer != null) {
+ // Convert from microseconds to milliseconds with rounding
+ long totalTime = (vibTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
+ int count = vibTimer.getCountLocked(which);
+ if (totalTime != 0) {
+ dumpLine(pw, uid, category, VIBRATOR_DATA, totalTime, count);
+ }
+ }
+
Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
if (processStats.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
@@ -1919,6 +1936,26 @@
}
}
+ Timer vibTimer = u.getVibratorOnTimer();
+ if (vibTimer != null) {
+ // Convert from microseconds to milliseconds with rounding
+ long totalTime = (vibTimer.getTotalTimeLocked(
+ batteryRealtime, which) + 500) / 1000;
+ int count = vibTimer.getCountLocked(which);
+ //timer.logState();
+ if (totalTime != 0) {
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Vibrator: ");
+ formatTimeMs(sb, totalTime);
+ sb.append("realtime (");
+ sb.append(count);
+ sb.append(" times)");
+ pw.println(sb.toString());
+ uidActivity = true;
+ }
+ }
+
Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
if (processStats.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index d69d2a6..52c89e8 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -434,12 +434,6 @@
/**
* Android X.X: "K". Just "K"
- *
- * <p>Applications targeting this or a later release will get these
- * new changes in behavior:</p>
- * <ul>
- * <li>Application home directory permissions are now {@code 0700}.</li>
- * </ul>
*/
public static final int K = CUR_DEVELOPMENT;
}
diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java
index 667ce68..d633486 100644
--- a/core/java/android/os/FileObserver.java
+++ b/core/java/android/os/FileObserver.java
@@ -32,7 +32,7 @@
*
* <p>Each FileObserver instance monitors a single file or directory.
* If a directory is monitored, events will be triggered for all files and
- * subdirectories (recursively) inside the monitored directory.</p>
+ * subdirectories inside the monitored directory.</p>
*
* <p>An event mask is used to specify which changes or actions to report.
* Event type constants are used to describe the possible changes in the
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index 2c2fe8a..15cedf9 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -20,8 +20,8 @@
interface IVibratorService
{
boolean hasVibrator();
- void vibrate(long milliseconds, IBinder token);
- void vibratePattern(in long[] pattern, int repeat, IBinder token);
+ void vibrate(String packageName, long milliseconds, IBinder token);
+ void vibratePattern(String packageName, in long[] pattern, int repeat, IBinder token);
void cancelVibrate(IBinder token);
}
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 7c5a47e..54ea385 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -16,6 +16,7 @@
package android.os;
+import android.content.Context;
import android.util.Log;
/**
@@ -26,10 +27,18 @@
public class SystemVibrator extends Vibrator {
private static final String TAG = "Vibrator";
+ private final String mPackageName;
private final IVibratorService mService;
private final Binder mToken = new Binder();
public SystemVibrator() {
+ mPackageName = null;
+ mService = IVibratorService.Stub.asInterface(
+ ServiceManager.getService("vibrator"));
+ }
+
+ public SystemVibrator(Context context) {
+ mPackageName = context.getPackageName();
mService = IVibratorService.Stub.asInterface(
ServiceManager.getService("vibrator"));
}
@@ -54,7 +63,7 @@
return;
}
try {
- mService.vibrate(milliseconds, mToken);
+ mService.vibrate(mPackageName, milliseconds, mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
}
@@ -71,7 +80,7 @@
// anyway
if (repeat < pattern.length) {
try {
- mService.vibratePattern(pattern, repeat, mToken);
+ mService.vibratePattern(mPackageName, pattern, repeat, mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
}
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index cc96152..d205253 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -16,6 +16,8 @@
package android.os;
+import java.io.PrintWriter;
+
/**
* Representation of a user on the device.
*/
@@ -152,6 +154,50 @@
}
/**
+ * Generate a text representation of the uid, breaking out its individual
+ * components -- user, app, isolated, etc.
+ * @hide
+ */
+ public static void formatUid(StringBuilder sb, int uid) {
+ if (uid < Process.FIRST_APPLICATION_UID) {
+ sb.append(uid);
+ } else {
+ sb.append('u');
+ sb.append(getUserId(uid));
+ final int appId = getAppId(uid);
+ if (appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID) {
+ sb.append('i');
+ sb.append(appId - Process.FIRST_ISOLATED_UID);
+ } else {
+ sb.append('a');
+ sb.append(appId);
+ }
+ }
+ }
+
+ /**
+ * Generate a text representation of the uid, breaking out its individual
+ * components -- user, app, isolated, etc.
+ * @hide
+ */
+ public static void formatUid(PrintWriter pw, int uid) {
+ if (uid < Process.FIRST_APPLICATION_UID) {
+ pw.print(uid);
+ } else {
+ pw.print('u');
+ pw.print(getUserId(uid));
+ final int appId = getAppId(uid);
+ if (appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID) {
+ pw.print('i');
+ pw.print(appId - Process.FIRST_ISOLATED_UID);
+ } else {
+ pw.print('a');
+ pw.print(appId);
+ }
+ }
+ }
+
+ /**
* Returns the user id of the current process
* @return user id of the current process
* @hide
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index d909362..122f8a1 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -503,8 +503,15 @@
mNumberOfBlocks = newNumberOfBlocks;
final int deltaLines = newLineCount - (endLine - startLine + 1);
- for (int i = firstBlock + numAddedBlocks; i < mNumberOfBlocks; i++) {
- mBlockEndLines[i] += deltaLines;
+ if (deltaLines != 0) {
+ // Display list whose index is >= mIndexFirstChangedBlock is valid
+ // but it needs to update its drawing location.
+ mIndexFirstChangedBlock = firstBlock + numAddedBlocks;
+ for (int i = mIndexFirstChangedBlock; i < mNumberOfBlocks; i++) {
+ mBlockEndLines[i] += deltaLines;
+ }
+ } else {
+ mIndexFirstChangedBlock = mNumberOfBlocks;
}
int blockIndex = firstBlock;
@@ -559,6 +566,20 @@
return mNumberOfBlocks;
}
+ /**
+ * @hide
+ */
+ public int getIndexFirstChangedBlock() {
+ return mIndexFirstChangedBlock;
+ }
+
+ /**
+ * @hide
+ */
+ public void setIndexFirstChangedBlock(int i) {
+ mIndexFirstChangedBlock = i;
+ }
+
@Override
public int getLineCount() {
return mInts.size() - 1;
@@ -697,6 +718,8 @@
private int[] mBlockIndices;
// Number of items actually currently being used in the above 2 arrays
private int mNumberOfBlocks;
+ // The first index of the blocks whose locations are changed
+ private int mIndexFirstChangedBlock;
private int mTopPadding, mBottomPadding;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 97287c3..a4e4f37 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4376,10 +4376,16 @@
if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
mPrivateFlags |= PFLAG_FOCUSED;
+ View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
+
if (mParent != null) {
mParent.requestChildFocus(this, this);
}
+ if (mAttachInfo != null) {
+ mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
+ }
+
onFocusChanged(true, direction, previouslyFocusedRect);
refreshDrawableState();
@@ -4486,7 +4492,9 @@
refreshDrawableState();
- ensureInputFocusOnFirstFocusable();
+ if (!rootViewRequestFocus()) {
+ notifyGlobalFocusCleared(this);
+ }
if (AccessibilityManager.getInstance(mContext).isEnabled()) {
notifyAccessibilityStateChanged();
@@ -4494,11 +4502,18 @@
}
}
- void ensureInputFocusOnFirstFocusable() {
+ void notifyGlobalFocusCleared(View oldFocus) {
+ if (oldFocus != null && mAttachInfo != null) {
+ mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
+ }
+ }
+
+ boolean rootViewRequestFocus() {
View root = getRootView();
if (root != null) {
- root.requestFocus();
+ return root.requestFocus();
}
+ return false;
}
/**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c274f27..a4898fc 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3697,7 +3697,9 @@
clearChildFocus = true;
}
- view.clearAccessibilityFocus();
+ if (view.isAccessibilityFocused()) {
+ view.clearAccessibilityFocus();
+ }
cancelTouchTarget(view);
cancelHoverTarget(view);
@@ -3719,11 +3721,9 @@
if (clearChildFocus) {
clearChildFocus(view);
- ensureInputFocusOnFirstFocusable();
- }
-
- if (view.isAccessibilityFocused()) {
- view.clearAccessibilityFocus();
+ if (!rootViewRequestFocus()) {
+ notifyGlobalFocusCleared(this);
+ }
}
onViewRemoved(view);
@@ -3765,7 +3765,7 @@
private void removeViewsInternal(int start, int count) {
final View focused = mFocused;
final boolean detach = mAttachInfo != null;
- View clearChildFocus = null;
+ boolean clearChildFocus = false;
final View[] children = mChildren;
final int end = start + count;
@@ -3779,10 +3779,12 @@
if (view == focused) {
view.unFocus();
- clearChildFocus = view;
+ clearChildFocus = true;
}
- view.clearAccessibilityFocus();
+ if (view.isAccessibilityFocused()) {
+ view.clearAccessibilityFocus();
+ }
cancelTouchTarget(view);
cancelHoverTarget(view);
@@ -3805,9 +3807,11 @@
removeFromArray(start, count);
- if (clearChildFocus != null) {
- clearChildFocus(clearChildFocus);
- ensureInputFocusOnFirstFocusable();
+ if (clearChildFocus) {
+ clearChildFocus(focused);
+ if (!rootViewRequestFocus()) {
+ notifyGlobalFocusCleared(focused);
+ }
}
}
@@ -3849,7 +3853,7 @@
final View focused = mFocused;
final boolean detach = mAttachInfo != null;
- View clearChildFocus = null;
+ boolean clearChildFocus = false;
needGlobalAttributesUpdate(false);
@@ -3862,10 +3866,12 @@
if (view == focused) {
view.unFocus();
- clearChildFocus = view;
+ clearChildFocus = true;
}
- view.clearAccessibilityFocus();
+ if (view.isAccessibilityFocused()) {
+ view.clearAccessibilityFocus();
+ }
cancelTouchTarget(view);
cancelHoverTarget(view);
@@ -3887,9 +3893,11 @@
children[i] = null;
}
- if (clearChildFocus != null) {
- clearChildFocus(clearChildFocus);
- ensureInputFocusOnFirstFocusable();
+ if (clearChildFocus) {
+ clearChildFocus(focused);
+ if (!rootViewRequestFocus()) {
+ notifyGlobalFocusCleared(focused);
+ }
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f9f955e..6a96893 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -169,9 +169,6 @@
int mSeq;
View mView;
- View mFocusedView;
- View mRealFocusedView; // this is not set to null in touch mode
- View mOldFocusedView;
View mAccessibilityFocusedHost;
AccessibilityNodeInfo mAccessibilityFocusedVirtualView;
@@ -269,7 +266,7 @@
boolean mScrollMayChange;
int mSoftInputMode;
- View mLastScrolledFocus;
+ WeakReference<View> mLastScrolledFocus;
int mScrollY;
int mCurScrollY;
Scroller mScroller;
@@ -1526,7 +1523,9 @@
} else if (!mSurface.isValid()) {
// If the surface has been removed, then reset the scroll
// positions.
- mLastScrolledFocus = null;
+ if (mLastScrolledFocus != null) {
+ mLastScrolledFocus.clear();
+ }
mScrollY = mCurScrollY = 0;
if (mScroller != null) {
mScroller.abortAnimation();
@@ -1802,13 +1801,11 @@
if (mView != null) {
if (!mView.hasFocus()) {
mView.requestFocus(View.FOCUS_FORWARD);
- mFocusedView = mRealFocusedView = mView.findFocus();
if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: requested focused view="
- + mFocusedView);
+ + mView.findFocus());
} else {
- mRealFocusedView = mView.findFocus();
if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: existing focused view="
- + mRealFocusedView);
+ + mView.findFocus());
}
}
if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_ANIMATING) != 0) {
@@ -2514,17 +2511,12 @@
// requestChildRectangleOnScreen() call (in which case 'rectangle'
// is non-null and we just want to scroll to whatever that
// rectangle is).
- View focus = mRealFocusedView;
-
- // When in touch mode, focus points to the previously focused view,
- // which may have been removed from the view hierarchy. The following
- // line checks whether the view is still in our hierarchy.
- if (focus == null || focus.mAttachInfo != mAttachInfo) {
- mRealFocusedView = null;
+ View focus = mView.findFocus();
+ if (focus == null) {
return false;
}
-
- if (focus != mLastScrolledFocus) {
+ View lastScrolledFocus = (mLastScrolledFocus != null) ? mLastScrolledFocus.get() : null;
+ if (lastScrolledFocus != null && focus != lastScrolledFocus) {
// If the focus has changed, then ignore any requests to scroll
// to a rectangle; first we want to make sure the entire focus
// view is visible.
@@ -2533,8 +2525,7 @@
if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Eval scroll: focus=" + focus
+ " rectangle=" + rectangle + " ci=" + ci
+ " vi=" + vi);
- if (focus == mLastScrolledFocus && !mScrollMayChange
- && rectangle == null) {
+ if (focus == lastScrolledFocus && !mScrollMayChange && rectangle == null) {
// Optimization: if the focus hasn't changed since last
// time, and no layout has happened, then just leave things
// as they are.
@@ -2544,7 +2535,7 @@
// We need to determine if the currently focused view is
// within the visible part of the window and, if not, apply
// a pan so it can be seen.
- mLastScrolledFocus = focus;
+ mLastScrolledFocus = new WeakReference<View>(focus);
mScrollMayChange = false;
if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Need to scroll?");
// Try to find the rectangle from the focus view.
@@ -2671,33 +2662,19 @@
}
public void requestChildFocus(View child, View focused) {
- checkThread();
-
if (DEBUG_INPUT_RESIZE) {
Log.v(TAG, "Request child focus: focus now " + focused);
}
-
- mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mOldFocusedView, focused);
+ checkThread();
scheduleTraversals();
-
- mFocusedView = mRealFocusedView = focused;
}
public void clearChildFocus(View child) {
- checkThread();
-
if (DEBUG_INPUT_RESIZE) {
Log.v(TAG, "Clearing child focus");
}
-
- mOldFocusedView = mFocusedView;
-
- // Invoke the listener only if there is no view to take focus
- if (focusSearch(null, View.FOCUS_FORWARD) == null) {
- mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mOldFocusedView, null);
- }
-
- mFocusedView = mRealFocusedView = null;
+ checkThread();
+ scheduleTraversals();
}
@Override
@@ -2714,14 +2691,13 @@
// the one case where will transfer focus away from the current one
// is if the current view is a view group that prefers to give focus
// to its children first AND the view is a descendant of it.
- mFocusedView = mView.findFocus();
- boolean descendantsHaveDibsOnFocus =
- (mFocusedView instanceof ViewGroup) &&
- (((ViewGroup) mFocusedView).getDescendantFocusability() ==
- ViewGroup.FOCUS_AFTER_DESCENDANTS);
- if (descendantsHaveDibsOnFocus && isViewDescendantOf(v, mFocusedView)) {
- // If a view gets the focus, the listener will be invoked from requestChildFocus()
- v.requestFocus();
+ View focused = mView.findFocus();
+ if (focused instanceof ViewGroup) {
+ ViewGroup group = (ViewGroup) focused;
+ if (group.getDescendantFocusability() == ViewGroup.FOCUS_AFTER_DESCENDANTS
+ && isViewDescendantOf(v, focused)) {
+ v.requestFocus();
+ }
}
}
}
@@ -3199,7 +3175,6 @@
// set yet.
final View focused = mView.findFocus();
if (focused != null && !focused.isFocusableInTouchMode()) {
-
final ViewGroup ancestorToTakeFocus =
findAncestorToTakeFocusInTouchMode(focused);
if (ancestorToTakeFocus != null) {
@@ -3208,10 +3183,7 @@
return ancestorToTakeFocus.requestFocus();
} else {
// nothing appropriate to have focus in touch mode, clear it out
- mView.unFocus();
- mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(focused, null);
- mFocusedView = null;
- mOldFocusedView = null;
+ focused.unFocus();
return true;
}
}
@@ -3246,12 +3218,11 @@
private boolean leaveTouchMode() {
if (mView != null) {
if (mView.hasFocus()) {
- // i learned the hard way to not trust mFocusedView :)
- mFocusedView = mView.findFocus();
- if (!(mFocusedView instanceof ViewGroup)) {
+ View focusedView = mView.findFocus();
+ if (!(focusedView instanceof ViewGroup)) {
// some view has focus, let it keep it
return false;
- } else if (((ViewGroup)mFocusedView).getDescendantFocusability() !=
+ } else if (((ViewGroup) focusedView).getDescendantFocusability() !=
ViewGroup.FOCUS_AFTER_DESCENDANTS) {
// some view group has focus, and doesn't prefer its children
// over itself for focus, so let them keep it.
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index 6251c45..d4e27bc 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -309,6 +309,7 @@
lp.type = LayoutParams.TYPE_VOLUME_OVERLAY;
lp.width = LayoutParams.WRAP_CONTENT;
lp.height = LayoutParams.WRAP_CONTENT;
+ lp.privateFlags |= LayoutParams.PRIVATE_FLAG_FORCE_SHOW_NAV_BAR;
window.setAttributes(lp);
window.addFlags(LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 3b31ff6..6a67d8b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -946,6 +946,13 @@
public static final int PRIVATE_FLAG_SHOW_FOR_ALL_USERS = 0x00000010;
/**
+ * Special flag for the volume overlay: force the window manager out of "hide nav bar"
+ * mode while the window is on screen.
+ *
+ * {@hide} */
+ public static final int PRIVATE_FLAG_FORCE_SHOW_NAV_BAR = 0x00000020;
+
+ /**
* Control flags that are private to the platform.
* @hide
*/
diff --git a/core/java/android/webkit/package.html b/core/java/android/webkit/package.html
index 4ed08da..7182488 100644
--- a/core/java/android/webkit/package.html
+++ b/core/java/android/webkit/package.html
@@ -1,7 +1,7 @@
<html>
<body>
-Provides tools for browsing the web.
-<p>The only classes or interfaces in this package intended for use by SDK
-developers are WebView, BroswerCallbackAdapter, BrowserCallback, and CookieManager.
+<p>Provides tools for browsing the web.
+<p>For more information about building apps with web-based content, see the
+<a href="{@docRoot}guide/webapps/overview.html">Web Apps Overview</a>.
</body>
</html>
\ No newline at end of file
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index 44f04db..97926a7 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -97,11 +97,11 @@
* Constructor
*
* @param context The current context.
- * @param textViewResourceId The resource ID for a layout file containing a TextView to use when
+ * @param resource The resource ID for a layout file containing a TextView to use when
* instantiating views.
*/
- public ArrayAdapter(Context context, int textViewResourceId) {
- init(context, textViewResourceId, 0, new ArrayList<T>());
+ public ArrayAdapter(Context context, int resource) {
+ init(context, resource, 0, new ArrayList<T>());
}
/**
@@ -120,12 +120,12 @@
* Constructor
*
* @param context The current context.
- * @param textViewResourceId The resource ID for a layout file containing a TextView to use when
+ * @param resource The resource ID for a layout file containing a TextView to use when
* instantiating views.
* @param objects The objects to represent in the ListView.
*/
- public ArrayAdapter(Context context, int textViewResourceId, T[] objects) {
- init(context, textViewResourceId, 0, Arrays.asList(objects));
+ public ArrayAdapter(Context context, int resource, T[] objects) {
+ init(context, resource, 0, Arrays.asList(objects));
}
/**
@@ -145,12 +145,12 @@
* Constructor
*
* @param context The current context.
- * @param textViewResourceId The resource ID for a layout file containing a TextView to use when
+ * @param resource The resource ID for a layout file containing a TextView to use when
* instantiating views.
* @param objects The objects to represent in the ListView.
*/
- public ArrayAdapter(Context context, int textViewResourceId, List<T> objects) {
- init(context, textViewResourceId, 0, objects);
+ public ArrayAdapter(Context context, int resource, List<T> objects) {
+ init(context, resource, 0, objects);
}
/**
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 41d6033..4eaa78a 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -124,7 +124,6 @@
InputMethodState mInputMethodState;
DisplayList[] mTextDisplayLists;
- int mLastLayoutHeight;
boolean mFrozenWithFocus;
boolean mSelectionMoved;
@@ -1289,20 +1288,11 @@
mTextDisplayLists = new DisplayList[ArrayUtils.idealObjectArraySize(0)];
}
- // If the height of the layout changes (usually when inserting or deleting a line,
- // but could be changes within a span), invalidate everything. We could optimize
- // more aggressively (for example, adding offsets to blocks) but it would be more
- // complex and we would only get the benefit in some cases.
- int layoutHeight = layout.getHeight();
- if (mLastLayoutHeight != layoutHeight) {
- invalidateTextDisplayList();
- mLastLayoutHeight = layoutHeight;
- }
-
DynamicLayout dynamicLayout = (DynamicLayout) layout;
int[] blockEndLines = dynamicLayout.getBlockEndLines();
int[] blockIndices = dynamicLayout.getBlockIndices();
final int numberOfBlocks = dynamicLayout.getNumberOfBlocks();
+ final int indexFirstChangedBlock = dynamicLayout.getIndexFirstChangedBlock();
int endOfPreviousBlock = -1;
int searchStartIndex = 0;
@@ -1327,7 +1317,8 @@
if (blockIsInvalid) blockDisplayList.invalidate();
}
- if (!blockDisplayList.isValid()) {
+ final boolean blockDisplayListIsInvalid = !blockDisplayList.isValid();
+ if (i >= indexFirstChangedBlock || blockDisplayListIsInvalid) {
final int blockBeginLine = endOfPreviousBlock + 1;
final int top = layout.getLineTop(blockBeginLine);
final int bottom = layout.getLineBottom(blockEndLine);
@@ -1344,24 +1335,30 @@
right = (int) (max + 0.5f);
}
- final HardwareCanvas hardwareCanvas = blockDisplayList.start();
- try {
- // Tighten the bounds of the viewport to the actual text size
- hardwareCanvas.setViewport(right - left, bottom - top);
- // The dirty rect should always be null for a display list
- hardwareCanvas.onPreDraw(null);
- // drawText is always relative to TextView's origin, this translation brings
- // this range of text back to the top left corner of the viewport
- hardwareCanvas.translate(-left, -top);
- layout.drawText(hardwareCanvas, blockBeginLine, blockEndLine);
- // No need to untranslate, previous context is popped after drawDisplayList
- } finally {
- hardwareCanvas.onPostDraw();
- blockDisplayList.end();
- blockDisplayList.setLeftTopRightBottom(left, top, right, bottom);
- // Same as drawDisplayList below, handled by our TextView's parent
- blockDisplayList.setClipChildren(false);
+ // Rebuild display list if it is invalid
+ if (blockDisplayListIsInvalid) {
+ final HardwareCanvas hardwareCanvas = blockDisplayList.start();
+ try {
+ // Tighten the bounds of the viewport to the actual text size
+ hardwareCanvas.setViewport(right - left, bottom - top);
+ // The dirty rect should always be null for a display list
+ hardwareCanvas.onPreDraw(null);
+ // drawText is always relative to TextView's origin, this translation brings
+ // this range of text back to the top left corner of the viewport
+ hardwareCanvas.translate(-left, -top);
+ layout.drawText(hardwareCanvas, blockBeginLine, blockEndLine);
+ // No need to untranslate, previous context is popped after drawDisplayList
+ } finally {
+ hardwareCanvas.onPostDraw();
+ blockDisplayList.end();
+ // Same as drawDisplayList below, handled by our TextView's parent
+ blockDisplayList.setClipChildren(false);
+ }
}
+
+ // Valid disply list whose index is >= indexFirstChangedBlock
+ // only needs to update its drawing location.
+ blockDisplayList.setLeftTopRightBottom(left, top, right, bottom);
}
((HardwareCanvas) canvas).drawDisplayList(blockDisplayList, null,
@@ -1369,6 +1366,8 @@
endOfPreviousBlock = blockEndLine;
}
+
+ dynamicLayout.setIndexFirstChangedBlock(numberOfBlocks);
} else {
// Boring layout is used for empty and hint text
layout.drawText(canvas, firstLine, lastLine);
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index b40260c..8c710ce 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -567,7 +567,10 @@
applied to the drawable, be sure to call setImageMatrix().
*/
public Matrix getImageMatrix() {
- return mMatrix;
+ if (mDrawMatrix == null) {
+ return Matrix.IDENTITY_MATRIX;
+ }
+ return mDrawMatrix;
}
public void setImageMatrix(Matrix matrix) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index d635de6..f8db622 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6459,7 +6459,6 @@
mDeferScroll = -1;
bringPointIntoView(Math.min(curs, mText.length()));
}
- if (changed && mEditor != null) mEditor.invalidateTextDisplayList();
}
private boolean isShowingHint() {
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
new file mode 100644
index 0000000..c934587
--- /dev/null
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+interface IAppOpsService {
+ int noteOperation(int code, int uid, String packageName);
+ int startOperation(int code, int uid, String packageName);
+ void finishOperation(int code, int uid, String packageName);
+ int noteTimedOperation(int code, int uid, String packageName, int duration);
+ void earlyFinishOperation(int code, int uid, String packageName);
+}
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 1a76461..823e19f 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -37,6 +37,8 @@
void noteStartWakelockFromSource(in WorkSource ws, int pid, String name, int type);
void noteStopWakelockFromSource(in WorkSource ws, int pid, String name, int type);
+ void noteVibratorOn(int uid, long durationMillis);
+ void noteVibratorOff(int uid);
void noteStartGps(int uid);
void noteStopGps(int uid);
void noteScreenOn();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 94e7a06..4d35a6b 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -16,14 +16,11 @@
package com.android.internal.os;
-import static android.net.NetworkStats.IFACE_ALL;
-import static android.net.NetworkStats.UID_ALL;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
-import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkStats;
import android.os.BatteryManager;
@@ -49,7 +46,6 @@
import android.util.SparseArray;
import android.util.TimeUtils;
-import com.android.internal.R;
import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.util.JournaledFile;
import com.google.android.collect.Sets;
@@ -87,7 +83,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 62 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 64 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -356,8 +352,8 @@
}
public static interface Unpluggable {
- void unplug(long batteryUptime, long batteryRealtime);
- void plug(long batteryUptime, long batteryRealtime);
+ void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime);
+ void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime);
}
/**
@@ -392,12 +388,12 @@
out.writeInt(mUnpluggedCount);
}
- public void unplug(long batteryUptime, long batteryRealtime) {
+ public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
mUnpluggedCount = mPluggedCount;
mCount.set(mPluggedCount);
}
- public void plug(long batteryUptime, long batteryRealtime) {
+ public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
mPluggedCount = mCount.get();
}
@@ -587,7 +583,7 @@
out.writeLong(mUnpluggedTime);
}
- public void unplug(long batteryUptime, long batteryRealtime) {
+ public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
if (DEBUG && mType < 0) {
Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime
+ " old mUnpluggedTime=" + mUnpluggedTime
@@ -602,7 +598,7 @@
}
}
- public void plug(long batteryUptime, long batteryRealtime) {
+ public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
if (DEBUG && mType < 0) {
Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime
+ " old mTotalTime=" + mTotalTime);
@@ -731,7 +727,7 @@
boolean mTrackingReportedValues;
/*
- * A sequnce counter, incremented once for each update of the stats.
+ * A sequence counter, incremented once for each update of the stats.
*/
int mUpdateVersion;
@@ -786,8 +782,8 @@
mCurrentReportedTotalTime = totalTime;
}
- public void unplug(long batteryUptime, long batteryRealtime) {
- super.unplug(batteryUptime, batteryRealtime);
+ public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+ super.unplug(elapsedRealtime, batteryUptime, batteryRealtime);
if (mTrackingReportedValues) {
mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
mUnpluggedReportedCount = mCurrentReportedCount;
@@ -795,8 +791,8 @@
mInDischarge = true;
}
- public void plug(long batteryUptime, long batteryRealtime) {
- super.plug(batteryUptime, batteryRealtime);
+ public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+ super.plug(elapsedRealtime, batteryUptime, batteryRealtime);
mInDischarge = false;
}
@@ -849,6 +845,141 @@
}
/**
+ * A timer that increments in batches. It does not run for durations, but just jumps
+ * for a pre-determined amount.
+ */
+ public static final class BatchTimer extends Timer {
+ final Uid mUid;
+
+ /**
+ * The last time at which we updated the timer. This is in elapsed realtime microseconds.
+ */
+ long mLastAddedTime;
+
+ /**
+ * The last duration that we added to the timer. This is in microseconds.
+ */
+ long mLastAddedDuration;
+
+ /**
+ * Whether we are currently in a discharge cycle.
+ */
+ boolean mInDischarge;
+
+ BatchTimer(Uid uid, int type, ArrayList<Unpluggable> unpluggables,
+ boolean inDischarge, Parcel in) {
+ super(type, unpluggables, in);
+ mUid = uid;
+ mLastAddedTime = in.readLong();
+ mLastAddedDuration = in.readLong();
+ mInDischarge = inDischarge;
+ }
+
+ BatchTimer(Uid uid, int type, ArrayList<Unpluggable> unpluggables,
+ boolean inDischarge) {
+ super(type, unpluggables);
+ mUid = uid;
+ mInDischarge = inDischarge;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, long batteryRealtime) {
+ super.writeToParcel(out, batteryRealtime);
+ out.writeLong(mLastAddedTime);
+ out.writeLong(mLastAddedDuration);
+ }
+
+ @Override
+ public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+ recomputeLastDuration(SystemClock.elapsedRealtime() * 1000, false);
+ mInDischarge = false;
+ super.plug(elapsedRealtime, batteryUptime, batteryRealtime);
+ }
+
+ @Override
+ public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+ recomputeLastDuration(elapsedRealtime, false);
+ mInDischarge = true;
+ // If we are still within the last added duration, then re-added whatever remains.
+ if (mLastAddedTime == elapsedRealtime) {
+ mTotalTime += mLastAddedDuration;
+ }
+ super.unplug(elapsedRealtime, batteryUptime, batteryRealtime);
+ }
+
+ @Override
+ public void logState(Printer pw, String prefix) {
+ super.logState(pw, prefix);
+ pw.println(prefix + "mLastAddedTime=" + mLastAddedTime
+ + " mLastAddedDuration=" + mLastAddedDuration);
+ }
+
+ private long computeOverage(long curTime) {
+ if (mLastAddedTime > 0) {
+ return mLastTime + mLastAddedDuration - curTime;
+ }
+ return 0;
+ }
+
+ private void recomputeLastDuration(long curTime, boolean abort) {
+ final long overage = computeOverage(curTime);
+ if (overage > 0) {
+ // Aborting before the duration ran out -- roll back the remaining
+ // duration. Only do this if currently discharging; otherwise we didn't
+ // actually add the time.
+ if (mInDischarge) {
+ mTotalTime -= overage;
+ }
+ if (abort) {
+ mLastAddedTime = 0;
+ } else {
+ mLastAddedTime = curTime;
+ mLastAddedDuration -= overage;
+ }
+ }
+ }
+
+ public void addDuration(BatteryStatsImpl stats, long durationMillis) {
+ final long now = SystemClock.elapsedRealtime() * 1000;
+ recomputeLastDuration(now, true);
+ mLastAddedTime = now;
+ mLastAddedDuration = durationMillis * 1000;
+ if (mInDischarge) {
+ mTotalTime += mLastAddedDuration;
+ mCount++;
+ }
+ }
+
+ public void abortLastDuration(BatteryStatsImpl stats) {
+ final long now = SystemClock.elapsedRealtime() * 1000;
+ recomputeLastDuration(now, true);
+ }
+
+ @Override
+ protected int computeCurrentCountLocked() {
+ return mCount;
+ }
+
+ @Override
+ protected long computeRunTimeLocked(long curBatteryRealtime) {
+ final long overage = computeOverage(SystemClock.elapsedRealtime() * 1000);
+ if (overage > 0) {
+ return mTotalTime = overage;
+ }
+ return mTotalTime;
+ }
+
+ @Override
+ boolean reset(BatteryStatsImpl stats, boolean detachIfReset) {
+ final long now = SystemClock.elapsedRealtime() * 1000;
+ recomputeLastDuration(now, true);
+ boolean stillActive = mLastAddedTime == now;
+ super.reset(stats, !stillActive && detachIfReset);
+ return !stillActive;
+ }
+ }
+
+ /**
* State for keeping track of timing information.
*/
public static final class StopwatchTimer extends Timer {
@@ -902,12 +1033,12 @@
out.writeLong(mUpdateTime);
}
- public void plug(long batteryUptime, long batteryRealtime) {
+ public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
if (mNesting > 0) {
if (DEBUG && mType < 0) {
Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
}
- super.plug(batteryUptime, batteryRealtime);
+ super.plug(elapsedRealtime, batteryUptime, batteryRealtime);
mUpdateTime = batteryRealtime;
if (DEBUG && mType < 0) {
Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
@@ -1443,7 +1574,7 @@
mHistoryOverflow = false;
}
- public void doUnplugLocked(long batteryUptime, long batteryRealtime) {
+ public void doUnplugLocked(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
NetworkStats.Entry entry = null;
// Track UID data usage
@@ -1462,7 +1593,7 @@
}
for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
- mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime);
+ mUnpluggables.get(i).unplug(elapsedRealtime, batteryUptime, batteryRealtime);
}
// Track both mobile and total overall data
@@ -1483,7 +1614,7 @@
mBluetoothPingCount = 0;
}
- public void doPlugLocked(long batteryUptime, long batteryRealtime) {
+ public void doPlugLocked(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
NetworkStats.Entry entry = null;
for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
@@ -1498,7 +1629,7 @@
}
}
for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
- mUnpluggables.get(i).plug(batteryUptime, batteryRealtime);
+ mUnpluggables.get(i).plug(elapsedRealtime, batteryUptime, batteryRealtime);
}
// Track both mobile and total overall data
@@ -2109,6 +2240,14 @@
getUidStatsLocked(uid).noteVideoTurnedOffLocked();
}
+ public void noteVibratorOnLocked(int uid, long durationMillis) {
+ getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
+ }
+
+ public void noteVibratorOffLocked(int uid) {
+ getUidStatsLocked(uid).noteVibratorOffLocked();
+ }
+
public void noteWifiRunningLocked(WorkSource ws) {
if (!mGlobalWifiRunning) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_RUNNING_FLAG;
@@ -2402,6 +2541,8 @@
boolean mVideoTurnedOn;
StopwatchTimer mVideoTurnedOnTimer;
+ BatchTimer mVibratorOnTimer;
+
Counter[] mUserActivityCounters;
/**
@@ -2439,10 +2580,6 @@
mWifiScanTimers, mUnpluggables);
mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
mWifiMulticastTimers, mUnpluggables);
- mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
- null, mUnpluggables);
- mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
- null, mUnpluggables);
}
@Override
@@ -2587,15 +2724,19 @@
}
}
+ public StopwatchTimer createAudioTurnedOnTimerLocked() {
+ if (mAudioTurnedOnTimer == null) {
+ mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
+ null, mUnpluggables);
+ }
+ return mAudioTurnedOnTimer;
+ }
+
@Override
public void noteAudioTurnedOnLocked() {
if (!mAudioTurnedOn) {
mAudioTurnedOn = true;
- if (mAudioTurnedOnTimer == null) {
- mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
- null, mUnpluggables);
- }
- mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
+ createAudioTurnedOnTimerLocked().startRunningLocked(BatteryStatsImpl.this);
}
}
@@ -2603,19 +2744,25 @@
public void noteAudioTurnedOffLocked() {
if (mAudioTurnedOn) {
mAudioTurnedOn = false;
- mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
+ if (mAudioTurnedOnTimer != null) {
+ mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
+ }
}
}
+ public StopwatchTimer createVideoTurnedOnTimerLocked() {
+ if (mVideoTurnedOnTimer == null) {
+ mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
+ null, mUnpluggables);
+ }
+ return mVideoTurnedOnTimer;
+ }
+
@Override
public void noteVideoTurnedOnLocked() {
if (!mVideoTurnedOn) {
mVideoTurnedOn = true;
- if (mVideoTurnedOnTimer == null) {
- mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
- null, mUnpluggables);
- }
- mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
+ createVideoTurnedOnTimerLocked().startRunningLocked(BatteryStatsImpl.this);
}
}
@@ -2623,7 +2770,27 @@
public void noteVideoTurnedOffLocked() {
if (mVideoTurnedOn) {
mVideoTurnedOn = false;
- mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
+ if (mVideoTurnedOnTimer != null) {
+ mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
+ }
+ }
+ }
+
+ public BatchTimer createVibratorOnTimerLocked() {
+ if (mVibratorOnTimer == null) {
+ mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON,
+ mUnpluggables, BatteryStatsImpl.this.mOnBatteryInternal);
+ }
+ return mVibratorOnTimer;
+ }
+
+ public void noteVibratorOnLocked(long durationMillis) {
+ createVibratorOnTimerLocked().addDuration(BatteryStatsImpl.this, durationMillis);
+ }
+
+ public void noteVibratorOffLocked() {
+ if (mVibratorOnTimer != null) {
+ mVibratorOnTimer.abortLastDuration(BatteryStatsImpl.this);
}
}
@@ -2677,6 +2844,11 @@
}
@Override
+ public Timer getVibratorOnTimer() {
+ return mVibratorOnTimer;
+ }
+
+ @Override
public void noteUserActivityLocked(int type) {
if (mUserActivityCounters == null) {
initUserActivityLocked();
@@ -2747,6 +2919,14 @@
active |= !mVideoTurnedOnTimer.reset(BatteryStatsImpl.this, false);
active |= mVideoTurnedOn;
}
+ if (mVibratorOnTimer != null) {
+ if (mVibratorOnTimer.reset(BatteryStatsImpl.this, false)) {
+ mVibratorOnTimer.detach();
+ mVibratorOnTimer = null;
+ } else {
+ active = true;
+ }
+ }
mLoadedTcpBytesReceived = mLoadedTcpBytesSent = 0;
mCurrentTcpBytesReceived = mCurrentTcpBytesSent = 0;
@@ -2832,9 +3012,11 @@
}
if (mAudioTurnedOnTimer != null) {
mAudioTurnedOnTimer.detach();
+ mAudioTurnedOnTimer = null;
}
if (mVideoTurnedOnTimer != null) {
mVideoTurnedOnTimer.detach();
+ mVideoTurnedOnTimer = null;
}
if (mUserActivityCounters != null) {
for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
@@ -2917,6 +3099,12 @@
} else {
out.writeInt(0);
}
+ if (mVibratorOnTimer != null) {
+ out.writeInt(1);
+ mVibratorOnTimer.writeToParcel(out, batteryRealtime);
+ } else {
+ out.writeInt(0);
+ }
if (mUserActivityCounters != null) {
out.writeInt(1);
for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
@@ -3016,6 +3204,12 @@
mVideoTurnedOnTimer = null;
}
if (in.readInt() != 0) {
+ mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON,
+ mUnpluggables, BatteryStatsImpl.this.mOnBatteryInternal, in);
+ } else {
+ mVibratorOnTimer = null;
+ }
+ if (in.readInt() != 0) {
mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
mUserActivityCounters[i] = new Counter(mUnpluggables, in);
@@ -3256,14 +3450,14 @@
mSpeedBins = new SamplingCounter[getCpuSpeedSteps()];
}
- public void unplug(long batteryUptime, long batteryRealtime) {
+ public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
mUnpluggedUserTime = mUserTime;
mUnpluggedSystemTime = mSystemTime;
mUnpluggedStarts = mStarts;
mUnpluggedForegroundTime = mForegroundTime;
}
- public void plug(long batteryUptime, long batteryRealtime) {
+ public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
}
void detach() {
@@ -3550,11 +3744,11 @@
mUnpluggables.add(this);
}
- public void unplug(long batteryUptime, long batteryRealtime) {
+ public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
mUnpluggedWakeups = mWakeups;
}
- public void plug(long batteryUptime, long batteryRealtime) {
+ public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
}
void detach() {
@@ -3712,13 +3906,13 @@
mUnpluggables.add(this);
}
- public void unplug(long batteryUptime, long batteryRealtime) {
+ public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime);
mUnpluggedStarts = mStarts;
mUnpluggedLaunches = mLaunches;
}
- public void plug(long batteryUptime, long batteryRealtime) {
+ public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
}
void detach() {
@@ -4367,7 +4561,7 @@
}
mDischargeAmountScreenOn = 0;
mDischargeAmountScreenOff = 0;
- doUnplugLocked(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
+ doUnplugLocked(realtime, mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
} else {
updateKernelWakelocksLocked();
mHistoryCur.batteryLevel = (byte)level;
@@ -4383,7 +4577,7 @@
mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
}
updateDischargeScreenLevelsLocked(mScreenOn, mScreenOn);
- doPlugLocked(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime));
+ doPlugLocked(realtime, getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime));
}
if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
if (mFile != null) {
@@ -5161,11 +5355,14 @@
}
u.mAudioTurnedOn = false;
if (in.readInt() != 0) {
- u.mAudioTurnedOnTimer.readSummaryFromParcelLocked(in);
+ u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
}
u.mVideoTurnedOn = false;
if (in.readInt() != 0) {
- u.mVideoTurnedOnTimer.readSummaryFromParcelLocked(in);
+ u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
+ }
+ if (in.readInt() != 0) {
+ u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
}
if (in.readInt() != 0) {
@@ -5367,6 +5564,12 @@
} else {
out.writeInt(0);
}
+ if (u.mVibratorOnTimer != null) {
+ out.writeInt(1);
+ u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+ } else {
+ out.writeInt(0);
+ }
if (u.mUserActivityCounters == null) {
out.writeInt(0);
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 61bc002..8ccc612 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -1052,6 +1052,7 @@
(mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
if (showTitle) {
x += positionChild(mTitleLayout, x, y, contentHeight, isLayoutRtl);
+ homeSlop = mTitleLayout.getWidth();
}
switch (mNavigationMode) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9822e63..e357255 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1327,21 +1327,6 @@
android:label="@string/permlab_writeGservices"
android:description="@string/permdesc_writeGservices" />
- <!-- @hide Change the screen compatibility mode of applications -->
- <permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
- android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="signature"
- android:label="@string/permlab_setScreenCompatibility"
- android:description="@string/permdesc_setScreenCompatibility" />
-
- <!-- Allows an application to modify the current configuration, such
- as locale. -->
- <permission android:name="android.permission.CHANGE_CONFIGURATION"
- android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="system|signature"
- android:label="@string/permlab_changeConfiguration"
- android:description="@string/permdesc_changeConfiguration" />
-
<!-- Allows an application to call
{@link android.app.ActivityManager#forceStopPackage}.
@hide -->
@@ -1621,6 +1606,13 @@
android:description="@string/permdesc_updateBatteryStats"
android:protectionLevel="signature|system" />
+ <!-- Allows an application to update application operation statistics. Not for
+ use by third party apps. @hide -->
+ <permission android:name="android.permission.UPDATE_APP_OPS_STATS"
+ android:label="@string/permlab_updateAppOpsStats"
+ android:description="@string/permdesc_updateAppOpsStats"
+ android:protectionLevel="signature|system" />
+
<!-- Allows an application to open windows that are for use by parts
of the system user interface. Not for use by third party apps. -->
<permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 21c4a64..a574468 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -321,7 +321,7 @@
<string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"允許應用程式啟動完整備份確認使用者介面 (不建議任何應用程式使用)。"</string>
<string name="permlab_internalSystemWindow" msgid="2148563628140193231">"顯示未授權視窗"</string>
<string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"允許應用程式為內部系統使用者介面建立視窗 (不建議一般應用程式使用)。"</string>
- <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"描繪其他應用程式"</string>
+ <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"在其他應用程式之上顯示内容"</string>
<string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"允許應用程式在其他應用程式頂層或使用者介面的特定部分繪圖。這可能會干擾您在所有應用程式中的介面使用行為,或是使您在其他應用程式中預期看到的內容發生變化。"</string>
<string name="permlab_setAnimationScale" msgid="2805103241153907174">"編輯全域動畫速度"</string>
<string name="permdesc_setAnimationScale" msgid="7690063428924343571">"允許應用程式隨時變更全域的動畫速度 (更快或更慢)。"</string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index cb8d0e5..6a93860 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -842,6 +842,12 @@
<string name="permdesc_updateBatteryStats">Allows the app to modify
collected battery statistics. Not for use by normal apps.</string>
+ <!-- [CHAR LIMIT=NONE] Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_updateAppOpsStats">modify app ops statistics</string>
+ <!-- [CHAR LIMIT=NONE] Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_updateAppOpsStats">Allows the app to modify
+ collected application operation statistics. Not for use by normal apps.</string>
+
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_backup">control system backup and restore</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/docs/downloads/brand/af_generic_rgb_wo.ai b/docs/downloads/brand/af_generic_rgb_wo.ai
new file mode 100644
index 0000000..2cec2e97
--- /dev/null
+++ b/docs/downloads/brand/af_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/ar_generic_rgb_wo.ai b/docs/downloads/brand/ar_generic_rgb_wo.ai
new file mode 100644
index 0000000..0eeb4f7
--- /dev/null
+++ b/docs/downloads/brand/ar_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/be_generic_rgb_wo.ai b/docs/downloads/brand/be_generic_rgb_wo.ai
new file mode 100644
index 0000000..3b82926
--- /dev/null
+++ b/docs/downloads/brand/be_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/bg_generic_rgb_wo.ai b/docs/downloads/brand/bg_generic_rgb_wo.ai
new file mode 100644
index 0000000..51e2a5d
--- /dev/null
+++ b/docs/downloads/brand/bg_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/ca_generic_rgb_wo.ai b/docs/downloads/brand/ca_generic_rgb_wo.ai
new file mode 100644
index 0000000..07b7fc5
--- /dev/null
+++ b/docs/downloads/brand/ca_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/cs_generic_rgb_wo.ai b/docs/downloads/brand/cs_generic_rgb_wo.ai
new file mode 100644
index 0000000..a998cb6
--- /dev/null
+++ b/docs/downloads/brand/cs_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/da_generic_rgb_wo.ai b/docs/downloads/brand/da_generic_rgb_wo.ai
new file mode 100644
index 0000000..d1bdc08
--- /dev/null
+++ b/docs/downloads/brand/da_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/de_app_rgb_wo.ai b/docs/downloads/brand/de_app_rgb_wo.ai
new file mode 100644
index 0000000..c0e8da3
--- /dev/null
+++ b/docs/downloads/brand/de_app_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/de_generic_rgb_wo.ai b/docs/downloads/brand/de_generic_rgb_wo.ai
new file mode 100644
index 0000000..e1463ef
--- /dev/null
+++ b/docs/downloads/brand/de_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/el_generic_rgb_wo.ai b/docs/downloads/brand/el_generic_rgb_wo.ai
new file mode 100644
index 0000000..0f7581b
--- /dev/null
+++ b/docs/downloads/brand/el_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/en_app_rgb_wo.ai b/docs/downloads/brand/en_app_rgb_wo.ai
new file mode 100644
index 0000000..db27314
--- /dev/null
+++ b/docs/downloads/brand/en_app_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/en_generic_rgb_wo.ai b/docs/downloads/brand/en_generic_rgb_wo.ai
new file mode 100644
index 0000000..57c1e47
--- /dev/null
+++ b/docs/downloads/brand/en_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/es-419_app_rgb_wo.ai b/docs/downloads/brand/es-419_app_rgb_wo.ai
new file mode 100644
index 0000000..9285921
--- /dev/null
+++ b/docs/downloads/brand/es-419_app_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/es-419_generic_rgb_wo.ai b/docs/downloads/brand/es-419_generic_rgb_wo.ai
new file mode 100644
index 0000000..1629e3e
--- /dev/null
+++ b/docs/downloads/brand/es-419_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/es_app_rgb_wo.ai b/docs/downloads/brand/es_app_rgb_wo.ai
new file mode 100644
index 0000000..78a3e5a4
--- /dev/null
+++ b/docs/downloads/brand/es_app_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/es_generic_rgb_wo.ai b/docs/downloads/brand/es_generic_rgb_wo.ai
new file mode 100644
index 0000000..bc839bc
--- /dev/null
+++ b/docs/downloads/brand/es_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/et_generic_rgb_wo.ai b/docs/downloads/brand/et_generic_rgb_wo.ai
new file mode 100644
index 0000000..693a73e
--- /dev/null
+++ b/docs/downloads/brand/et_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/fa_generic_rgb_wo.ai b/docs/downloads/brand/fa_generic_rgb_wo.ai
new file mode 100644
index 0000000..d6a0a8b
--- /dev/null
+++ b/docs/downloads/brand/fa_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/fi_generic_rgb_wo.ai b/docs/downloads/brand/fi_generic_rgb_wo.ai
new file mode 100644
index 0000000..1b18681
--- /dev/null
+++ b/docs/downloads/brand/fi_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/fil_generic_rgb_wo.ai b/docs/downloads/brand/fil_generic_rgb_wo.ai
new file mode 100644
index 0000000..958568a
--- /dev/null
+++ b/docs/downloads/brand/fil_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/fr_app_rgb_wo.ai b/docs/downloads/brand/fr_app_rgb_wo.ai
new file mode 100644
index 0000000..288c6da
--- /dev/null
+++ b/docs/downloads/brand/fr_app_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/fr_generic_rgb_wo.ai b/docs/downloads/brand/fr_generic_rgb_wo.ai
new file mode 100644
index 0000000..a542afc
--- /dev/null
+++ b/docs/downloads/brand/fr_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/hr_generic_rgb_wo.ai b/docs/downloads/brand/hr_generic_rgb_wo.ai
new file mode 100644
index 0000000..266257e
--- /dev/null
+++ b/docs/downloads/brand/hr_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/hu_generic_rgb_wo.ai b/docs/downloads/brand/hu_generic_rgb_wo.ai
new file mode 100644
index 0000000..dd436b6
--- /dev/null
+++ b/docs/downloads/brand/hu_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/id-in_generic_rgb_wo.ai b/docs/downloads/brand/id-in_generic_rgb_wo.ai
new file mode 100644
index 0000000..62d0be1
--- /dev/null
+++ b/docs/downloads/brand/id-in_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/it_app_rgb_wo.ai b/docs/downloads/brand/it_app_rgb_wo.ai
new file mode 100644
index 0000000..32024e4
--- /dev/null
+++ b/docs/downloads/brand/it_app_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/it_generic_rgb_wo.ai b/docs/downloads/brand/it_generic_rgb_wo.ai
new file mode 100644
index 0000000..a483b36
--- /dev/null
+++ b/docs/downloads/brand/it_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/iw-he_generic_rgb_wo.ai b/docs/downloads/brand/iw-he_generic_rgb_wo.ai
new file mode 100644
index 0000000..52c9641
--- /dev/null
+++ b/docs/downloads/brand/iw-he_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/ja_app_rgb_wo.ai b/docs/downloads/brand/ja_app_rgb_wo.ai
new file mode 100644
index 0000000..dacf38d
--- /dev/null
+++ b/docs/downloads/brand/ja_app_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/ja_generic_rgb_wo.ai b/docs/downloads/brand/ja_generic_rgb_wo.ai
new file mode 100644
index 0000000..fdfb9545
--- /dev/null
+++ b/docs/downloads/brand/ja_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/ko_app_rgb_wo.ai b/docs/downloads/brand/ko_app_rgb_wo.ai
new file mode 100644
index 0000000..4463149
--- /dev/null
+++ b/docs/downloads/brand/ko_app_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/ko_generic_rgb_wo.ai b/docs/downloads/brand/ko_generic_rgb_wo.ai
new file mode 100644
index 0000000..0d2d8bd
--- /dev/null
+++ b/docs/downloads/brand/ko_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/lt_generic_rgb_wo.ai b/docs/downloads/brand/lt_generic_rgb_wo.ai
new file mode 100644
index 0000000..fc679c7
--- /dev/null
+++ b/docs/downloads/brand/lt_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/lv_generic_rgb_wo.ai b/docs/downloads/brand/lv_generic_rgb_wo.ai
new file mode 100644
index 0000000..b07b28b
--- /dev/null
+++ b/docs/downloads/brand/lv_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/ms_generic_rgb_wo.ai b/docs/downloads/brand/ms_generic_rgb_wo.ai
new file mode 100644
index 0000000..c2f052e
--- /dev/null
+++ b/docs/downloads/brand/ms_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/nl_app_rgb_wo.ai b/docs/downloads/brand/nl_app_rgb_wo.ai
new file mode 100644
index 0000000..60d1ad8
--- /dev/null
+++ b/docs/downloads/brand/nl_app_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/nl_generic_rgb_wo.ai b/docs/downloads/brand/nl_generic_rgb_wo.ai
new file mode 100644
index 0000000..03eed23
--- /dev/null
+++ b/docs/downloads/brand/nl_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/no_generic_rgb_wo.ai b/docs/downloads/brand/no_generic_rgb_wo.ai
new file mode 100644
index 0000000..703e99a
--- /dev/null
+++ b/docs/downloads/brand/no_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/pl_generic_rgb_wo.ai b/docs/downloads/brand/pl_generic_rgb_wo.ai
new file mode 100644
index 0000000..fac15d2
--- /dev/null
+++ b/docs/downloads/brand/pl_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/pt-br_app_rgb_wo.ai b/docs/downloads/brand/pt-br_app_rgb_wo.ai
new file mode 100644
index 0000000..686455d
--- /dev/null
+++ b/docs/downloads/brand/pt-br_app_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/pt-br_generic_rgb_wo.ai b/docs/downloads/brand/pt-br_generic_rgb_wo.ai
new file mode 100644
index 0000000..00379cc
--- /dev/null
+++ b/docs/downloads/brand/pt-br_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/pt-pt_app_rgb_wo.ai b/docs/downloads/brand/pt-pt_app_rgb_wo.ai
new file mode 100644
index 0000000..bd19a28
--- /dev/null
+++ b/docs/downloads/brand/pt-pt_app_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/pt-pt_generic_rgb_wo.ai b/docs/downloads/brand/pt-pt_generic_rgb_wo.ai
new file mode 100644
index 0000000..29476cc
--- /dev/null
+++ b/docs/downloads/brand/pt-pt_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/ro_generic_rgb_wo.ai b/docs/downloads/brand/ro_generic_rgb_wo.ai
new file mode 100644
index 0000000..6152a94
--- /dev/null
+++ b/docs/downloads/brand/ro_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/ru_generic_rgb_wo.ai b/docs/downloads/brand/ru_generic_rgb_wo.ai
new file mode 100644
index 0000000..1e73a61
--- /dev/null
+++ b/docs/downloads/brand/ru_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/sk_generic_rgb_wo.ai b/docs/downloads/brand/sk_generic_rgb_wo.ai
new file mode 100644
index 0000000..50735bd
--- /dev/null
+++ b/docs/downloads/brand/sk_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/sl_generic_rgb_wo.ai b/docs/downloads/brand/sl_generic_rgb_wo.ai
new file mode 100644
index 0000000..96f4708
--- /dev/null
+++ b/docs/downloads/brand/sl_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/sr_generic_rgb_wo.ai b/docs/downloads/brand/sr_generic_rgb_wo.ai
new file mode 100644
index 0000000..53dacd9
--- /dev/null
+++ b/docs/downloads/brand/sr_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/sv_generic_rgb_wo.ai b/docs/downloads/brand/sv_generic_rgb_wo.ai
new file mode 100644
index 0000000..f148dd3
--- /dev/null
+++ b/docs/downloads/brand/sv_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/sw_generic_rgb_wo.ai b/docs/downloads/brand/sw_generic_rgb_wo.ai
new file mode 100644
index 0000000..00d660c
--- /dev/null
+++ b/docs/downloads/brand/sw_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/th_generic_rgb_wo.ai b/docs/downloads/brand/th_generic_rgb_wo.ai
new file mode 100644
index 0000000..b24eff6
--- /dev/null
+++ b/docs/downloads/brand/th_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/tr_generic_rgb_wo.ai b/docs/downloads/brand/tr_generic_rgb_wo.ai
new file mode 100644
index 0000000..39db427
--- /dev/null
+++ b/docs/downloads/brand/tr_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/uk_generic_rgb_wo.ai b/docs/downloads/brand/uk_generic_rgb_wo.ai
new file mode 100644
index 0000000..81f510f
--- /dev/null
+++ b/docs/downloads/brand/uk_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/vi_generic_rgb_wo.ai b/docs/downloads/brand/vi_generic_rgb_wo.ai
new file mode 100644
index 0000000..5a0c796
--- /dev/null
+++ b/docs/downloads/brand/vi_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/zh-cn_generic_rgb_wo.ai b/docs/downloads/brand/zh-cn_generic_rgb_wo.ai
new file mode 100644
index 0000000..078b024
--- /dev/null
+++ b/docs/downloads/brand/zh-cn_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/zh-hk_generic_rgb_wo.ai b/docs/downloads/brand/zh-hk_generic_rgb_wo.ai
new file mode 100644
index 0000000..6d3bf0e
--- /dev/null
+++ b/docs/downloads/brand/zh-hk_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/zh-tw_generic_rgb_wo.ai b/docs/downloads/brand/zh-tw_generic_rgb_wo.ai
new file mode 100644
index 0000000..55d34ba
--- /dev/null
+++ b/docs/downloads/brand/zh-tw_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/downloads/brand/zu_generic_rgb_wo.ai b/docs/downloads/brand/zu_generic_rgb_wo.ai
new file mode 100644
index 0000000..cfc14d1
--- /dev/null
+++ b/docs/downloads/brand/zu_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/html/distribute/googleplay/promote/badge-files.jd b/docs/html/distribute/googleplay/promote/badge-files.jd
new file mode 100644
index 0000000..92001ed
--- /dev/null
+++ b/docs/html/distribute/googleplay/promote/badge-files.jd
@@ -0,0 +1,289 @@
+page.title=Google Play Badge Files
+@jd:body
+
+
+
+
+<style>
+table tr td {border:0}
+</style>
+
+<p>The following links provide the Adobe® Illustrator® (.ai) file for the
+two Google Play badges.</p>
+
+<hr>
+<img src="{@docRoot}images/brand/en_generic_rgb_wo_60.png" alt="Get It On Google Play">
+
+<div style="clear:left"> </div>
+
+<div class="col-4" style="margin-left:0">
+
+ <a href="{@docRoot}downloads/brand/en_generic_rgb_wo.ai">English (English)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/af_generic_rgb_wo.ai">Afrikaans (Afrikaans)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/ar_generic_rgb_wo.ai">العربية (Arabic)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/be_generic_rgb_wo.ai">Беларуская (Belarusian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/bg_generic_rgb_wo.ai">български (Bulgarian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/ca_generic_rgb_wo.ai">Català (Catalan)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/zh-cn_generic_rgb_wo.ai">中文 (中国) (Chinese)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/zh-hk_generic_rgb_wo.ai">中文(香港) (Chinese Hong Kong)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/zh-tw_generic_rgb_wo.ai">中文 (台灣) (Chinese Taiwan)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/hr_generic_rgb_wo.ai">Hrvatski (Croatian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/cs_generic_rgb_wo.ai">Česky (Czech)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/da_generic_rgb_wo.ai">Dansk (Danish)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/nl_generic_rgb_wo.ai">Nederlands (Dutch)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/et_generic_rgb_wo.ai">Eesti keel (Estonian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/fa_generic_rgb_wo.ai">فارسی (Farsi Persian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/fil_generic_rgb_wo.ai">Tagalog (Filipino)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/fi_generic_rgb_wo.ai">Suomi (Finnish)</a><br/>
+
+</div>
+
+<div class="col-4">
+
+ <a href="{@docRoot}downloads/brand/fr_generic_rgb_wo.ai">Français (French)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/de_generic_rgb_wo.ai">Deutsch (German)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/el_generic_rgb_wo.ai">Ελληνικά (Greek)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/iw-he_generic_rgb_wo.ai">עברית (Hebrew)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/hu_generic_rgb_wo.ai">Magyar (Hungarian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/id-in_generic_rgb_wo.ai">Bahasa Indonesia (Indonesian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/it_generic_rgb_wo.ai">Italiano (Italian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/ja_generic_rgb_wo.ai">日本語 (Japanese)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/ko_generic_rgb_wo.ai">한국어 (Korean)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/lv_generic_rgb_wo.ai">Latviski (Latvian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/lt_generic_rgb_wo.ai">Lietuviškai (Lithuanian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/ms_generic_rgb_wo.ai">Bahasa Melayu (Malay)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/no_generic_rgb_wo.ai">Norsk (Norwegian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/pl_generic_rgb_wo.ai">Polski (Polish)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/pt-pt_generic_rgb_wo.ai">Português (Portuguese)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/pt-br_generic_rgb_wo.ai">Português Brasil (Portuguese Brazil)</a><br/>
+
+</div>
+
+<div class="col-4" style="margin-right:0">
+
+ <a href="{@docRoot}downloads/brand/ro_generic_rgb_wo.ai">Românã (Romanian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/ru_generic_rgb_wo.ai">Pусский (Russian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/sr_generic_rgb_wo.ai">Српски / srpski (Serbian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/sk_generic_rgb_wo.ai">Slovenčina (Slovak)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/sl_generic_rgb_wo.ai">Slovenščina (Slovenian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/es_generic_rgb_wo.ai">Español (Spanish)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/es-419_generic_rgb_wo.ai">Español Latinoamérica (Spanish Latin America)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/sv_generic_rgb_wo.ai">Svenska (Swedish)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/sw_generic_rgb_wo.ai">Kiswahili (Swahili)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/th_generic_rgb_wo.ai">ภาษาไทย (Thai)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/tr_generic_rgb_wo.ai">Türkçe (Turkish)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/uk_generic_rgb_wo.ai">Українська (Ukrainian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/vi_generic_rgb_wo.ai">Tiếng Việt (Vietnamese)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/zu_generic_rgb_wo.ai">isiZulu (Zulu)</a><br/>
+
+</div>
+<div style="clear:left"> </div>
+
+
+
+
+
+
+<hr>
+<img src="{@docRoot}images/brand/en_app_rgb_wo_60.png" alt="Android App On Google Play">
+
+<div style="clear:left"> </div>
+
+<div class="col-8" style="margin-left:0">
+
+ <a href="{@docRoot}downloads/brand/en_app_rgb_wo.ai">English (English)</a><br/>
+
+<!--
+ <a href="{@docRoot}downloads/brand/af_app_rgb_wo.ai">Afrikaans (Afrikaans)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/ar_app_rgb_wo.ai">العربية (Arabic)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/be_app_rgb_wo.ai">Беларуская (Belarusian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/bg_app_rgb_wo.ai">български (Bulgarian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/ca_app_rgb_wo.ai">Català (Catalan)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/zh-cn_app_rgb_wo.ai">中文 (中国) (Chinese)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/zh-hk_app_rgb_wo.ai">中文(香港) (Chinese Hong Kong)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/zh-tw_app_rgb_wo.ai">中文 (台灣) (Chinese Taiwan)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/hr_app_rgb_wo.ai">Hrvatski (Croatian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/cs_app_rgb_wo.ai">Česky (Czech)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/da_app_rgb_wo.ai">Dansk (Danish)</a><br/>
+-->
+
+ <a href="{@docRoot}downloads/brand/nl_app_rgb_wo.ai">Nederlands (Dutch)</a><br/>
+
+<!--
+ <a href="{@docRoot}downloads/brand/et_app_rgb_wo.ai">Eesti keel (Estonian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/fa_app_rgb_wo.ai">فارسی (Farsi Persian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/fil_app_rgb_wo.ai">Tagalog (Filipino)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/fi_app_rgb_wo.ai">Suomi (Finnish)</a><br/>
+
+</div>
+
+<div class="col-4">
+-->
+
+ <a href="{@docRoot}downloads/brand/fr_app_rgb_wo.ai">Français (French)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/de_app_rgb_wo.ai">Deutsch (German)</a><br/>
+
+<!--
+ <a href="{@docRoot}downloads/brand/el_app_rgb_wo.ai">Ελληνικά (Greek)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/iw-he_app_rgb_wo.ai">עברית (Hebrew)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/hu_app_rgb_wo.ai">Magyar (Hungarian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/id-in_app_rgb_wo.ai">Bahasa Indonesia (Indonesian)</a><br/>
+-->
+
+ <a href="{@docRoot}downloads/brand/it_app_rgb_wo.ai">Italiano (Italian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/ja_app_rgb_wo.ai">日本語 (Japanese)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/ko_app_rgb_wo.ai">한국어 (Korean)</a><br/>
+
+<!--
+ <a href="{@docRoot}downloads/brand/lv_app_rgb_wo.ai">Latviski (Latvian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/lt_app_rgb_wo.ai">Lietuviškai (Lithuanian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/ms_app_rgb_wo.ai">Bahasa Melayu (Malay)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/no_app_rgb_wo.ai">Norsk (Norwegian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/pl_app_rgb_wo.ai">Polski (Polish)</a><br/>
+-->
+
+ <a href="{@docRoot}downloads/brand/pt-pt_app_rgb_wo.ai">Português (Portuguese)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/pt-br_app_rgb_wo.ai">Português Brasil (Portuguese Brazil)</a><br/>
+
+
+<!--
+</div>
+
+<div class="col-4" style="margin-right:0">
+ <a href="{@docRoot}downloads/brand/ro_app_rgb_wo.ai">Românã (Romanian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/ru_app_rgb_wo.ai">Pусский (Russian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/sr_app_rgb_wo.ai">Српски / srpski (Serbian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/sk_app_rgb_wo.ai">Slovenčina (Slovak)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/sl_app_rgb_wo.ai">Slovenščina (Slovenian)</a><br/>
+-->
+
+ <a href="{@docRoot}downloads/brand/es_app_rgb_wo.ai">Español (Spanish)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/es-419_app_rgb_wo.ai">Español Latinoamérica (Spanish Latin America)</a><br/>
+
+<!--
+ <a href="{@docRoot}downloads/brand/sv_app_rgb_wo.ai">Svenska (Swedish)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/sw_app_rgb_wo.ai">Kiswahili (Swahili)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/th_app_rgb_wo.ai">ภาษาไทย (Thai)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/tr_app_rgb_wo.ai">Türkçe (Turkish)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/uk_app_rgb_wo.ai">Українська (Ukrainian)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/vi_app_rgb_wo.ai">Tiếng Việt (Vietnamese)</a><br/>
+
+ <a href="{@docRoot}downloads/brand/zu_app_rgb_wo.ai">isiZulu (Zulu)</a><br/>
+-->
+
+</div>
+<div style="clear:left"> </div>
+
+
+
+
+
+
+<h2>Guidelines</h2>
+
+ <ul>
+ <li>Do not modify the color, proportions, spacing or any other aspect of the badge image.
+ </li>
+ <li>When used alongside logos for other application marketplaces, the Google Play logo
+ should be of equal or greater size.</li>
+ <li>When used online, the badge should link to either:
+ <ul>
+ <li>A list of products published by you, for example:<br />
+ <span style="margin-left:1em;">http://play.google.com/store/search?q=<em>publisherName</em></span>
+ </li>
+ <li>A specific app product details page within Google Play, for example:<br />
+ <span style="margin-left:1em;">http://play.google.com/store/apps/details?id=<em>packageName</em></span>
+ </li>
+ </ul>
+ </li>
+ </ul>
+
+<p>For more information, see the
+<a href="{@docRoot}distribute/googleplay/promote/brand.html#brand-google_play">Brand
+Guidelines</a>.
+
+
+<p>To quickly create a badge that links to your apps on Google Play,
+use the <a
+href="{@docRoot}distribute/googleplay/promote/badges.html">Googe Play badge generator</a>.</p>
+
+
+
\ No newline at end of file
diff --git a/docs/html/distribute/googleplay/promote/badges.jd b/docs/html/distribute/googleplay/promote/badges.jd
index 90e8c0d..0027f59 100644
--- a/docs/html/distribute/googleplay/promote/badges.jd
+++ b/docs/html/distribute/googleplay/promote/badges.jd
@@ -13,7 +13,7 @@
wraps your screenshots in real device artwork.</p>
<p>For guidelines when using the Google Play badge and other brand assets,
-see the <a href="{@docRoot}distribute/googleplay/promote/brand.html">Brand
+see the <a href="{@docRoot}distribute/googleplay/promote/brand.html#brand-google_play">Brand
Guidelines</a>.</p>
<style type="text/css">
@@ -56,9 +56,12 @@
<script type="text/javascript">
+// locales for which we have the 'app' badge
+var APP_LANGS = ['it','pt-br','pt-pt','nl','ko','ja','fr','es','es-419','en','de'];
+
// variables for creating 'try it out' demo button
-var imagePath = "http://developer.android.com/images/brand/"
-var linkStart = "<a href=\"http://play.google.com/store/";
+var imagePath = "https://developer.android.com/images/brand/"
+var linkStart = "<a href=\"https://play.google.com/store/";
var imageStart = "\">\n"
+ " <img alt=\"";
// leaves opening for the alt text value
@@ -67,7 +70,7 @@
var imageEnd = ".png\" />\n</a>";
// variables for creating code snippet
-var linkStartCode = "<a href=\"http://play.google.com/store/";
+var linkStartCode = "<a href=\"https://play.google.com/store/";
var imageStartCode = "\">\n"
+ " <img alt=\"";
// leaves opening for the alt text value
@@ -77,8 +80,9 @@
/** Generate the HTML snippet and demo based on form values */
function buildButton(form) {
- var selectedValue = $('form input[type=radio]:checked').val();
- var altText = selectedValue.indexOf("get_it") != -1 ? "Get it on Google Play" : "Android app on Google Play";
+ var lang = $('#locale option:selected').val();
+ var selectedValue = lang + $('form input[type=radio]:checked').val();
+ var altText = selectedValue.indexOf("generic") != -1 ? "Get it on Google Play" : "Android app on Google Play";
if (form["package"].value != "com.example.android") {
$("#preview").show();
@@ -144,6 +148,33 @@
return false;
}
+/** Switch the badge urls for selected language */
+function changeBadgeLang() {
+ var lang = $('#locale option:selected').val();
+
+ // check if we have the 'app' badge for this lang and show notice if not
+ $("div.button-row.error").remove(); // remove any existing instance of error message
+ if ($.inArray(lang,APP_LANGS) == -1) {
+ $("div.button-row.app").hide();
+ $("div.button-row.app").after('<div class="button-row error"><p class="note" style="margin:1em 0 -1em">'
+ + 'Sorry, we currently don\'t have the '
+ + '<em>Android app on Google Play</em> badge translated for '
+ + $("select#locale option[value="+lang+"]").attr("title")
+ + '.<br>Please check back later or instead use the <em>Get it on Google Play</em> badge below.'
+ + '</p></div>');
+ } else {
+ $("div.button-row.app").show(); // show the 'app' badge row
+ }
+
+ $('.button-row img').each(function() {
+ var id = $(this).parent().attr('for');
+ var imgName = lang + $('input#'+id).attr('value') + '.png';
+ var lastSlash = $(this).attr('src').lastIndexOf('/');
+ var imgPath = $(this).attr('src').substring(0, lastSlash+1);
+ $(this).attr('src', imgPath + imgName);
+ });
+}
+
/** When the doc is ready, find the inputs and color the input grey if the value is the example
text. This is necessary to handle back-navigation, which can auto-fill the form with previous
values (and text should not be grey) */
@@ -163,7 +194,106 @@
</script>
<form class="button-form">
- <label class="block" for="package">Package name:</label>
+ <label class="block" for="locale">Language:</label>
+ <select id="locale" style="display:block;float:left;margin:0"
+ onchange="changeBadgeLang()">
+ <option title="Afrikaans"
+ value="af">Afrikaans</option>
+ <option title="Arabic"
+ value="ar">العربية</option>
+ <option title="Belarusian"
+ value="be">Беларуская</option>
+ <option title="Bulgarian"
+ value="bg">Български</option>
+ <option title="Catalan"
+ value="ca">Català</option>
+ <option title="Chinese (China)"
+ value="zh-cn">中文 (中国)</option>
+ <option title="Chinese (Hong Kong)"
+ value="zh-hk">中文(香港)</option>
+ <option title="Chinese (Taiwan)"
+ value="zh-tw">中文 (台灣)</option>
+ <option title="Croatian"
+ value="hr">Hrvatski</option>
+ <option title="Czech"
+ value="cs">Česky</option>
+ <option title="Danish"
+ value="da">Dansk</option>
+ <option title="Dutch"
+ value="nl">Nederlands</option>
+ <option title="Estonian"
+ value="et">Eesti</option>
+ <option title="Farsi - Persian"
+ value="fa">فارسی</option>
+ <option title="Filipino"
+ value="fil">Tagalog</option>
+ <option title="Finnish"
+ value="fi">Suomi</option>
+ <option title="French"
+ value="fr">Français</option>
+ <option title="German"
+ value="de">Deutsch</option>
+ <option title="Greek"
+ value="el">Ελληνικά</option>
+ <option title="English"
+ value="en" selected="true">English</option>
+ <option title="Hebrew"
+ value="iw-he">עברית</option>
+ <option title="Hungarian"
+ value="hu">Magyar</option>
+ <option title="Indonesian"
+ value="id-in">Bahasa Indonesia</option>
+ <option title="Italian"
+ value="it">Italiano</option>
+ <option title="Japanese"
+ value="ja">日本語</option>
+ <option title="Korean"
+ value="ko">한국어</option>
+ <option title="Latvian"
+ value="lv">Latviešu</option>
+ <option title="Lithuanian"
+ value="lt">Lietuviškai</option>
+ <option title="Malay"
+ value="ms">Bahasa Melayu</option>
+ <option title="Norwegian"
+ value="no">Norsk (bokmål)</option>
+ <option title="Polish"
+ value="pl">Polski</option>
+ <option title="Portuguese (Brazil)"
+ value="pt-br">Português (Brasil)</option>
+ <option title="Portuguese (Portugal)"
+ value="pt-pt">Português (Portugal)</option>
+ <option title="Romanian"
+ value="ro">Română</option>
+ <option title="Russian"
+ value="ru">Русский</option>
+ <option title="Serbian"
+ value="sr">Српски / srpski</option>
+ <option title="Slovak"
+ value="sk">Slovenčina</option>
+ <option title="Slovenian"
+ value="sl">Slovenščina</option>
+ <option title="Spanish (Spain)"
+ value="es">Español (España)</option>
+ <option title="Spanish (Latin America)"
+ value="es-419">Español (Latinoamérica)</option>
+ <option title="Swedish"
+ value="sv">Svenska</option>
+ <option title="Swahili"
+ value="sw">Kiswahili</option>
+ <option title="Thai"
+ value="th">ไทย</option>
+ <option title="Turkish"
+ value="tr">Türkçe</option>
+ <option title="Ukrainian"
+ value="uk">Українська</option>
+ <option title="Vietnamese"
+ value="vi">Tiếng Việt</option>
+ <option title="Zulu"
+ value="zu">isiZulu</option>
+ </select>
+ <p style="clear:both;margin:0"> </p>
+ <label class="block" for="package" style="clear:left">Package name:</label>
<input class="text" type="text" id="package" name="package"
value="com.example.android"
default="com.example.android"
@@ -185,27 +315,27 @@
<br/><br/>
-<div class="button-row">
- <input type="radio" name="buttonStyle" value="en_app_rgb_wo_45" id="ws" checked="checked" />
+<div class="button-row app">
+ <input type="radio" name="buttonStyle" value="_app_rgb_wo_45" id="ws" />
<label for="ws"><img src="{@docRoot}images/brand/en_app_rgb_wo_45.png"
alt="Android app on Google Play (small)" /></label>
- <input type="radio" name="buttonStyle" value="en_app_rgb_wo_60" id="wm" />
+ <input type="radio" name="buttonStyle" value="_app_rgb_wo_60" id="wm" />
<label for="wm"><img src="{@docRoot}images/brand/en_app_rgb_wo_60.png"
alt="Android app on Google Play (large)" /></label>
</div>
<div class="button-row">
- <input type="radio" name="buttonStyle" value="en_generic_rgb_wo_45" id="ns" />
+ <input type="radio" name="buttonStyle" value="_generic_rgb_wo_45" id="ns" checked="checked" />
<label for="ns"><img src="{@docRoot}images/brand/en_generic_rgb_wo_45.png"
alt="Get it on Google Play (small)" /></label>
- <input type="radio" name="buttonStyle" value="en_generic_rgb_wo_60" id="nm" />
+ <input type="radio" name="buttonStyle" value="_generic_rgb_wo_60" id="nm" />
<label for="nm"><img src="{@docRoot}images/brand/en_generic_rgb_wo_60.png"
alt="Get it on Google Play (large)" /></label>
</div>
- <input onclick="return buildButton(this.parentNode);"
+ <input class="button" onclick="return buildButton(this.parentNode);"
type="button" value="Build my badge" style="padding:10px" />
<br/>
</form>
diff --git a/docs/html/distribute/googleplay/promote/brand.jd b/docs/html/distribute/googleplay/promote/brand.jd
index 63b1f03..cea6d2c 100644
--- a/docs/html/distribute/googleplay/promote/brand.jd
+++ b/docs/html/distribute/googleplay/promote/brand.jd
@@ -118,8 +118,8 @@
<p>You may use the Google Play Store icon, but you may not modify it.</p>
<p>As mentioned above, when referring to the Google Play Store app in copy, use the full name:
-"Google Play Store." However, when labelling the Google Play Store icon directly, it's OK to use
-"Play Store" without "Google" (which is how the icon is labelled on a device).</p>
+"Google Play Store." However, when labeling the Google Play Store icon directly, it's OK to use
+"Play Store" alone to accurately reflect the icon label as it appears on a device.</p>
<h4>Google Play badge</h4>
@@ -128,16 +128,14 @@
<img src="{@docRoot}images/brand/en_app_rgb_wo_60.png" alt="">
<p style="text-align:center">
<a href="{@docRoot}images/brand/en_app_rgb_wo_45.png">129x45</a> |
- <a href="{@docRoot}images/brand/en_app_rgb_wo_60.png">172x60</a><br>
- <a href="{@docRoot}downloads/brand/en_app_rgb_wo.ai">Illustrator (.ai)</a></p>
+ <a href="{@docRoot}images/brand/en_app_rgb_wo_60.png">172x60</a></p>
</div>
<div style="float:right;clear:right;width:172px;margin-left:30px">
<img src="{@docRoot}images/brand/en_generic_rgb_wo_60.png" alt="">
<p style="text-align:center">
<a href="{@docRoot}images/brand/en_generic_rgb_wo_45.png">129x45</a> |
- <a href="{@docRoot}images/brand/en_generic_rgb_wo_60.png">172x60</a><br>
- <a href="{@docRoot}downloads/brand/en_generic_rgb_wo.ai">Illustrator (.ai)</a></p>
+ <a href="{@docRoot}images/brand/en_generic_rgb_wo_60.png">172x60</a></p>
</div>
<p>The "Get it on Google Play" and "Android App on Google Play" logos are badges that you
@@ -160,14 +158,19 @@
</ul>
</li>
</ul>
-
- <p>For your convenience, you can use the
- <a href="{@docRoot}distribute/googleplay/promote/badges.html">Googe Play badge generator</a>
- to create badges that link to your apps on Google Play.</p>
+
+ <p>To quickly create a badge that links to your apps on Google Play,
+ use the <a
+ href="{@docRoot}distribute/googleplay/promote/badges.html">Googe Play badge generator</a>
+ (provides the badge in over 40 languages).</p>
+
+ <p>To create your own size, download an Adobe® Illustrator® (.ai) file for the
+ <a href="{@docRoot}distribute/googleplay/promote/badge-files.html">Google Play
+ badge in over 40 languages</a>.</p>
<p>For details on all the ways that you can link to your product details page in Google Play,
see <a href="{@docRoot}distribute/googleplay/promote/linking.html">Linking to your products</a></p>
-<p>If you are not sure you meet these criteria, <a href=
+<p>If you are not sure you meet these brand guidelines, <a href=
"http://services.google.com/permissions/application">please contact us</a>. </p>
diff --git a/docs/html/google/play/billing/billing_integrate.jd b/docs/html/google/play/billing/billing_integrate.jd
index 405c58a..3f6df927 100644
--- a/docs/html/google/play/billing/billing_integrate.jd
+++ b/docs/html/google/play/billing/billing_integrate.jd
@@ -111,20 +111,21 @@
<pre>
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- bindService(new
- Intent("com.android.vending.billing.InAppBillingService.BIND"),
- mServiceConn, Context.BIND_AUTO_CREATE);
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ bindService(new
+ Intent("com.android.vending.billing.InAppBillingService.BIND"),
+ mServiceConn, Context.BIND_AUTO_CREATE);
</pre>
<p>You can now use the mService reference to communicate with the Google Play service.</p>
<p class="note"><strong>Important:</strong> Remember to unbind from the In-app Billing service when you are done with your {@link android.app.Activity}. If you don’t unbind, the open service connection could cause your device’s performance to degrade. This example shows how to perform the unbind operation on a service connection to In-app Billing called {@code mServiceConn} by overriding the activity’s {@link android.app.Activity#onDestroy onDestroy} method.</p>
<pre>
@Override
public void onDestroy() {
- if (mServiceConn != null) {
- unbindService(mServiceConn);
- }
+ super.onDestroy();
+ if (mServiceConn != null) {
+ unbindService(mServiceConn);
+ }
}
</pre>
diff --git a/docs/html/guide/topics/connectivity/wifip2p.jd b/docs/html/guide/topics/connectivity/wifip2p.jd
index 82c9abd..bbf30fd 100644
--- a/docs/html/guide/topics/connectivity/wifip2p.jd
+++ b/docs/html/guide/topics/connectivity/wifip2p.jd
@@ -237,16 +237,16 @@
*/
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
- private WifiP2pManager manager;
- private Channel channel;
- private MyWiFiActivity activity;
+ private WifiP2pManager mManager;
+ private Channel mChannel;
+ private MyWiFiActivity mActivity;
public WiFiDirectBroadcastReceiver(WifiP2pManager manager, Channel channel,
MyWifiActivity activity) {
super();
- this.manager = manager;
- this.channel = channel;
- this.activity = activity;
+ this.mManager = manager;
+ this.mChannel = channel;
+ this.mActivity = activity;
}
@Override
@@ -333,7 +333,7 @@
...
mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(this, getMainLooper(), null);
- mReceiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
+ mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
...
}
</pre>
@@ -397,7 +397,7 @@
that the discovery process succeeded and does not provide any information about the actual peers
that it discovered, if any:</p>
<pre>
-manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
+mManager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
...
@@ -425,8 +425,8 @@
// request available peers from the wifi p2p manager. This is an
// asynchronous call and the calling activity is notified with a
// callback on PeerListListener.onPeersAvailable()
- if (manager != null) {
- manager.requestPeers(channel, myPeerListListener);
+ if (mManager != null) {
+ mManager.requestPeers(mChannel, myPeerListListener);
}
}
</pre>
@@ -453,7 +453,7 @@
WifiP2pDevice device;
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
-manager.connect(channel, config, new ActionListener() {
+mManager.connect(mChannel, config, new ActionListener() {
@Override
public void onSuccess() {
diff --git a/docs/html/guide/topics/manifest/manifest-intro.jd b/docs/html/guide/topics/manifest/manifest-intro.jd
index a130f7d..d25a513 100644
--- a/docs/html/guide/topics/manifest/manifest-intro.jd
+++ b/docs/html/guide/topics/manifest/manifest-intro.jd
@@ -115,6 +115,7 @@
<a href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></a>
<a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html"><grant-uri-permission /></a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html"><meta-data /></a>
+ <a href="{@docRoot}guide/topics/manifest/path-permission-element.html"><path-permission /></a>
<a href="{@docRoot}guide/topics/manifest/provider-element.html"></provider></a>
<a href="{@docRoot}guide/topics/manifest/uses-library-element.html"><uses-library /></a>
diff --git a/docs/html/guide/topics/ui/layout/gridview.jd b/docs/html/guide/topics/ui/layout/gridview.jd
index 67bdd0f0..84c3dab 100644
--- a/docs/html/guide/topics/ui/layout/gridview.jd
+++ b/docs/html/guide/topics/ui/layout/gridview.jd
@@ -170,7 +170,7 @@
be cropped toward the center (if necessary).</li>
<li>{@link android.widget.ImageView#setPadding(int,int,int,int)} defines the padding for all
sides. (Note that, if the images have different aspect-ratios, then less
-padding will cause for more cropping of the image if it does not match
+padding will cause more cropping of the image if it does not match
the dimensions given to the ImageView.)</li>
</ul>
diff --git a/docs/html/images/brand/af_generic_rgb_wo_45.png b/docs/html/images/brand/af_generic_rgb_wo_45.png
new file mode 100644
index 0000000..bf774ab
--- /dev/null
+++ b/docs/html/images/brand/af_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/af_generic_rgb_wo_60.png b/docs/html/images/brand/af_generic_rgb_wo_60.png
new file mode 100644
index 0000000..0487c7f
--- /dev/null
+++ b/docs/html/images/brand/af_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/ar_generic_rgb_wo_45.png b/docs/html/images/brand/ar_generic_rgb_wo_45.png
new file mode 100644
index 0000000..bdb0ff6
--- /dev/null
+++ b/docs/html/images/brand/ar_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/ar_generic_rgb_wo_60.png b/docs/html/images/brand/ar_generic_rgb_wo_60.png
new file mode 100644
index 0000000..ba9fc69
--- /dev/null
+++ b/docs/html/images/brand/ar_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/be_generic_rgb_wo_45.png b/docs/html/images/brand/be_generic_rgb_wo_45.png
new file mode 100644
index 0000000..bec6c7a
--- /dev/null
+++ b/docs/html/images/brand/be_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/be_generic_rgb_wo_60.png b/docs/html/images/brand/be_generic_rgb_wo_60.png
new file mode 100644
index 0000000..53ad2a11
--- /dev/null
+++ b/docs/html/images/brand/be_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/bg_generic_rgb_wo_45.png b/docs/html/images/brand/bg_generic_rgb_wo_45.png
new file mode 100644
index 0000000..9a27471
--- /dev/null
+++ b/docs/html/images/brand/bg_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/bg_generic_rgb_wo_60.png b/docs/html/images/brand/bg_generic_rgb_wo_60.png
new file mode 100644
index 0000000..5143a66
--- /dev/null
+++ b/docs/html/images/brand/bg_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/ca_generic_rgb_wo_45.png b/docs/html/images/brand/ca_generic_rgb_wo_45.png
new file mode 100644
index 0000000..698a4cd
--- /dev/null
+++ b/docs/html/images/brand/ca_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/ca_generic_rgb_wo_60.png b/docs/html/images/brand/ca_generic_rgb_wo_60.png
new file mode 100644
index 0000000..e943de1
--- /dev/null
+++ b/docs/html/images/brand/ca_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/cs_generic_rgb_wo_45.png b/docs/html/images/brand/cs_generic_rgb_wo_45.png
new file mode 100644
index 0000000..b97b805
--- /dev/null
+++ b/docs/html/images/brand/cs_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/cs_generic_rgb_wo_60.png b/docs/html/images/brand/cs_generic_rgb_wo_60.png
new file mode 100644
index 0000000..9656c2e
--- /dev/null
+++ b/docs/html/images/brand/cs_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/da_generic_rgb_wo_45.png b/docs/html/images/brand/da_generic_rgb_wo_45.png
new file mode 100644
index 0000000..541ba29
--- /dev/null
+++ b/docs/html/images/brand/da_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/da_generic_rgb_wo_60.png b/docs/html/images/brand/da_generic_rgb_wo_60.png
new file mode 100644
index 0000000..d974154
--- /dev/null
+++ b/docs/html/images/brand/da_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/de_app_rgb_wo_45.png b/docs/html/images/brand/de_app_rgb_wo_45.png
new file mode 100644
index 0000000..db48df2
--- /dev/null
+++ b/docs/html/images/brand/de_app_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/de_app_rgb_wo_60.png b/docs/html/images/brand/de_app_rgb_wo_60.png
new file mode 100644
index 0000000..9e0f757
--- /dev/null
+++ b/docs/html/images/brand/de_app_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/de_generic_rgb_wo_45.png b/docs/html/images/brand/de_generic_rgb_wo_45.png
new file mode 100644
index 0000000..1396f79
--- /dev/null
+++ b/docs/html/images/brand/de_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/de_generic_rgb_wo_60.png b/docs/html/images/brand/de_generic_rgb_wo_60.png
new file mode 100644
index 0000000..f2df4a4
--- /dev/null
+++ b/docs/html/images/brand/de_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/el_generic_rgb_wo_45.png b/docs/html/images/brand/el_generic_rgb_wo_45.png
new file mode 100644
index 0000000..adaea5f
--- /dev/null
+++ b/docs/html/images/brand/el_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/el_generic_rgb_wo_60.png b/docs/html/images/brand/el_generic_rgb_wo_60.png
new file mode 100644
index 0000000..37ae3bc
--- /dev/null
+++ b/docs/html/images/brand/el_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/es-419_app_rgb_wo_45.png b/docs/html/images/brand/es-419_app_rgb_wo_45.png
new file mode 100644
index 0000000..3fb9a3f
--- /dev/null
+++ b/docs/html/images/brand/es-419_app_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/es-419_app_rgb_wo_60.png b/docs/html/images/brand/es-419_app_rgb_wo_60.png
new file mode 100644
index 0000000..1dfb820
--- /dev/null
+++ b/docs/html/images/brand/es-419_app_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/es-419_generic_rgb_wo_45.png b/docs/html/images/brand/es-419_generic_rgb_wo_45.png
new file mode 100644
index 0000000..b89274d
--- /dev/null
+++ b/docs/html/images/brand/es-419_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/es-419_generic_rgb_wo_60.png b/docs/html/images/brand/es-419_generic_rgb_wo_60.png
new file mode 100644
index 0000000..23d7705
--- /dev/null
+++ b/docs/html/images/brand/es-419_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/es_app_rgb_wo_45.png b/docs/html/images/brand/es_app_rgb_wo_45.png
new file mode 100644
index 0000000..ad5e61a
--- /dev/null
+++ b/docs/html/images/brand/es_app_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/es_app_rgb_wo_60.png b/docs/html/images/brand/es_app_rgb_wo_60.png
new file mode 100644
index 0000000..6796ad3
--- /dev/null
+++ b/docs/html/images/brand/es_app_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/es_generic_rgb_wo_45.png b/docs/html/images/brand/es_generic_rgb_wo_45.png
new file mode 100644
index 0000000..b89274d
--- /dev/null
+++ b/docs/html/images/brand/es_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/es_generic_rgb_wo_60.png b/docs/html/images/brand/es_generic_rgb_wo_60.png
new file mode 100644
index 0000000..23d7705
--- /dev/null
+++ b/docs/html/images/brand/es_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/et_generic_rgb_wo_45.png b/docs/html/images/brand/et_generic_rgb_wo_45.png
new file mode 100644
index 0000000..0e267381
--- /dev/null
+++ b/docs/html/images/brand/et_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/et_generic_rgb_wo_60.png b/docs/html/images/brand/et_generic_rgb_wo_60.png
new file mode 100644
index 0000000..a99dee1
--- /dev/null
+++ b/docs/html/images/brand/et_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/fa_generic_rgb_wo_45.png b/docs/html/images/brand/fa_generic_rgb_wo_45.png
new file mode 100644
index 0000000..25827f6
--- /dev/null
+++ b/docs/html/images/brand/fa_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/fa_generic_rgb_wo_60.png b/docs/html/images/brand/fa_generic_rgb_wo_60.png
new file mode 100644
index 0000000..5118909
--- /dev/null
+++ b/docs/html/images/brand/fa_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/fi_generic_rgb_wo_45.png b/docs/html/images/brand/fi_generic_rgb_wo_45.png
new file mode 100644
index 0000000..93dc4fc
--- /dev/null
+++ b/docs/html/images/brand/fi_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/fi_generic_rgb_wo_60.png b/docs/html/images/brand/fi_generic_rgb_wo_60.png
new file mode 100644
index 0000000..95eff07
--- /dev/null
+++ b/docs/html/images/brand/fi_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/fil_generic_rgb_wo_45.png b/docs/html/images/brand/fil_generic_rgb_wo_45.png
new file mode 100644
index 0000000..7e74e62
--- /dev/null
+++ b/docs/html/images/brand/fil_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/fil_generic_rgb_wo_60.png b/docs/html/images/brand/fil_generic_rgb_wo_60.png
new file mode 100644
index 0000000..8f02743
--- /dev/null
+++ b/docs/html/images/brand/fil_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/fr_app_rgb_wo_45.png b/docs/html/images/brand/fr_app_rgb_wo_45.png
new file mode 100644
index 0000000..14219e3
--- /dev/null
+++ b/docs/html/images/brand/fr_app_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/fr_app_rgb_wo_60.png b/docs/html/images/brand/fr_app_rgb_wo_60.png
new file mode 100644
index 0000000..af58843
--- /dev/null
+++ b/docs/html/images/brand/fr_app_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/fr_generic_rgb_wo_45.png b/docs/html/images/brand/fr_generic_rgb_wo_45.png
new file mode 100644
index 0000000..3e1768f
--- /dev/null
+++ b/docs/html/images/brand/fr_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/fr_generic_rgb_wo_60.png b/docs/html/images/brand/fr_generic_rgb_wo_60.png
new file mode 100644
index 0000000..5c307f5
--- /dev/null
+++ b/docs/html/images/brand/fr_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/hr_generic_rgb_wo_45.png b/docs/html/images/brand/hr_generic_rgb_wo_45.png
new file mode 100644
index 0000000..b8acaac
--- /dev/null
+++ b/docs/html/images/brand/hr_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/hr_generic_rgb_wo_60.png b/docs/html/images/brand/hr_generic_rgb_wo_60.png
new file mode 100644
index 0000000..4fe6c7b
--- /dev/null
+++ b/docs/html/images/brand/hr_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/hu_generic_rgb_wo_45.png b/docs/html/images/brand/hu_generic_rgb_wo_45.png
new file mode 100644
index 0000000..3b2184d
--- /dev/null
+++ b/docs/html/images/brand/hu_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/hu_generic_rgb_wo_60.png b/docs/html/images/brand/hu_generic_rgb_wo_60.png
new file mode 100644
index 0000000..d6572be
--- /dev/null
+++ b/docs/html/images/brand/hu_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/id-in_generic_rgb_wo_45.png b/docs/html/images/brand/id-in_generic_rgb_wo_45.png
new file mode 100644
index 0000000..17ce069
--- /dev/null
+++ b/docs/html/images/brand/id-in_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/id-in_generic_rgb_wo_60.png b/docs/html/images/brand/id-in_generic_rgb_wo_60.png
new file mode 100644
index 0000000..ad067ce
--- /dev/null
+++ b/docs/html/images/brand/id-in_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/it_app_rgb_wo_45.png b/docs/html/images/brand/it_app_rgb_wo_45.png
new file mode 100644
index 0000000..16a137e
--- /dev/null
+++ b/docs/html/images/brand/it_app_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/it_app_rgb_wo_60.png b/docs/html/images/brand/it_app_rgb_wo_60.png
new file mode 100644
index 0000000..27123dc
--- /dev/null
+++ b/docs/html/images/brand/it_app_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/it_generic_rgb_wo_45.png b/docs/html/images/brand/it_generic_rgb_wo_45.png
new file mode 100644
index 0000000..ee5f85e
--- /dev/null
+++ b/docs/html/images/brand/it_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/it_generic_rgb_wo_60.png b/docs/html/images/brand/it_generic_rgb_wo_60.png
new file mode 100644
index 0000000..03ea5ba
--- /dev/null
+++ b/docs/html/images/brand/it_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/iw-he_generic_rgb_wo_45.png b/docs/html/images/brand/iw-he_generic_rgb_wo_45.png
new file mode 100644
index 0000000..1d03c77
--- /dev/null
+++ b/docs/html/images/brand/iw-he_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/iw-he_generic_rgb_wo_60.png b/docs/html/images/brand/iw-he_generic_rgb_wo_60.png
new file mode 100644
index 0000000..decfdae
--- /dev/null
+++ b/docs/html/images/brand/iw-he_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/ja_app_rgb_wo_45.png b/docs/html/images/brand/ja_app_rgb_wo_45.png
new file mode 100644
index 0000000..6af7582
--- /dev/null
+++ b/docs/html/images/brand/ja_app_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/ja_app_rgb_wo_60.png b/docs/html/images/brand/ja_app_rgb_wo_60.png
new file mode 100644
index 0000000..e197e12
--- /dev/null
+++ b/docs/html/images/brand/ja_app_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/ja_generic_rgb_wo_45.png b/docs/html/images/brand/ja_generic_rgb_wo_45.png
new file mode 100644
index 0000000..5f5281a
--- /dev/null
+++ b/docs/html/images/brand/ja_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/ja_generic_rgb_wo_60.png b/docs/html/images/brand/ja_generic_rgb_wo_60.png
new file mode 100644
index 0000000..fcb4c9c
--- /dev/null
+++ b/docs/html/images/brand/ja_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/ko_app_rgb_wo_45.png b/docs/html/images/brand/ko_app_rgb_wo_45.png
new file mode 100644
index 0000000..f0b427e
--- /dev/null
+++ b/docs/html/images/brand/ko_app_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/ko_app_rgb_wo_60.png b/docs/html/images/brand/ko_app_rgb_wo_60.png
new file mode 100644
index 0000000..6ccb673
--- /dev/null
+++ b/docs/html/images/brand/ko_app_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/ko_generic_rgb_wo_45.png b/docs/html/images/brand/ko_generic_rgb_wo_45.png
new file mode 100644
index 0000000..61ae04a
--- /dev/null
+++ b/docs/html/images/brand/ko_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/ko_generic_rgb_wo_60.png b/docs/html/images/brand/ko_generic_rgb_wo_60.png
new file mode 100644
index 0000000..9c14e36
--- /dev/null
+++ b/docs/html/images/brand/ko_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/lt_generic_rgb_wo_45.png b/docs/html/images/brand/lt_generic_rgb_wo_45.png
new file mode 100644
index 0000000..96564d5
--- /dev/null
+++ b/docs/html/images/brand/lt_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/lt_generic_rgb_wo_60.png b/docs/html/images/brand/lt_generic_rgb_wo_60.png
new file mode 100644
index 0000000..2c6c1bf
--- /dev/null
+++ b/docs/html/images/brand/lt_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/lv_generic_rgb_wo_45.png b/docs/html/images/brand/lv_generic_rgb_wo_45.png
new file mode 100644
index 0000000..8182ca5
--- /dev/null
+++ b/docs/html/images/brand/lv_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/lv_generic_rgb_wo_60.png b/docs/html/images/brand/lv_generic_rgb_wo_60.png
new file mode 100644
index 0000000..5c0b3d2
--- /dev/null
+++ b/docs/html/images/brand/lv_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/ms_generic_rgb_wo_45.png b/docs/html/images/brand/ms_generic_rgb_wo_45.png
new file mode 100644
index 0000000..d6ccc6b
--- /dev/null
+++ b/docs/html/images/brand/ms_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/ms_generic_rgb_wo_60.png b/docs/html/images/brand/ms_generic_rgb_wo_60.png
new file mode 100644
index 0000000..6e1c34d
--- /dev/null
+++ b/docs/html/images/brand/ms_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/nl_app_rgb_wo_45.png b/docs/html/images/brand/nl_app_rgb_wo_45.png
new file mode 100644
index 0000000..f06ed04
--- /dev/null
+++ b/docs/html/images/brand/nl_app_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/nl_app_rgb_wo_60.png b/docs/html/images/brand/nl_app_rgb_wo_60.png
new file mode 100644
index 0000000..f2c797d
--- /dev/null
+++ b/docs/html/images/brand/nl_app_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/nl_generic_rgb_wo_45.png b/docs/html/images/brand/nl_generic_rgb_wo_45.png
new file mode 100644
index 0000000..6b5826d
--- /dev/null
+++ b/docs/html/images/brand/nl_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/nl_generic_rgb_wo_60.png b/docs/html/images/brand/nl_generic_rgb_wo_60.png
new file mode 100644
index 0000000..cb11afda
--- /dev/null
+++ b/docs/html/images/brand/nl_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/no_generic_rgb_wo_45.png b/docs/html/images/brand/no_generic_rgb_wo_45.png
new file mode 100644
index 0000000..fb390d8
--- /dev/null
+++ b/docs/html/images/brand/no_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/no_generic_rgb_wo_60.png b/docs/html/images/brand/no_generic_rgb_wo_60.png
new file mode 100644
index 0000000..e83dce7
--- /dev/null
+++ b/docs/html/images/brand/no_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/pl_generic_rgb_wo_45.png b/docs/html/images/brand/pl_generic_rgb_wo_45.png
new file mode 100644
index 0000000..78caded
--- /dev/null
+++ b/docs/html/images/brand/pl_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/pl_generic_rgb_wo_60.png b/docs/html/images/brand/pl_generic_rgb_wo_60.png
new file mode 100644
index 0000000..2d956fb
--- /dev/null
+++ b/docs/html/images/brand/pl_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/pt-br_app_rgb_wo_45.png b/docs/html/images/brand/pt-br_app_rgb_wo_45.png
new file mode 100644
index 0000000..065998b
--- /dev/null
+++ b/docs/html/images/brand/pt-br_app_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/pt-br_app_rgb_wo_60.png b/docs/html/images/brand/pt-br_app_rgb_wo_60.png
new file mode 100644
index 0000000..1ce0a6c
--- /dev/null
+++ b/docs/html/images/brand/pt-br_app_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/pt-br_generic_rgb_wo_45.png b/docs/html/images/brand/pt-br_generic_rgb_wo_45.png
new file mode 100644
index 0000000..a661d44
--- /dev/null
+++ b/docs/html/images/brand/pt-br_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/pt-br_generic_rgb_wo_60.png b/docs/html/images/brand/pt-br_generic_rgb_wo_60.png
new file mode 100644
index 0000000..402af71
--- /dev/null
+++ b/docs/html/images/brand/pt-br_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/pt-pt_app_rgb_wo_45.png b/docs/html/images/brand/pt-pt_app_rgb_wo_45.png
new file mode 100644
index 0000000..0b50959
--- /dev/null
+++ b/docs/html/images/brand/pt-pt_app_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/pt-pt_app_rgb_wo_60.png b/docs/html/images/brand/pt-pt_app_rgb_wo_60.png
new file mode 100644
index 0000000..65dd887
--- /dev/null
+++ b/docs/html/images/brand/pt-pt_app_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/pt-pt_generic_rgb_wo_45.png b/docs/html/images/brand/pt-pt_generic_rgb_wo_45.png
new file mode 100644
index 0000000..a616cf1
--- /dev/null
+++ b/docs/html/images/brand/pt-pt_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/pt-pt_generic_rgb_wo_60.png b/docs/html/images/brand/pt-pt_generic_rgb_wo_60.png
new file mode 100644
index 0000000..36a7b83
--- /dev/null
+++ b/docs/html/images/brand/pt-pt_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/ro_generic_rgb_wo_45.png b/docs/html/images/brand/ro_generic_rgb_wo_45.png
new file mode 100644
index 0000000..c18a548
--- /dev/null
+++ b/docs/html/images/brand/ro_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/ro_generic_rgb_wo_60.png b/docs/html/images/brand/ro_generic_rgb_wo_60.png
new file mode 100644
index 0000000..b8f3433
--- /dev/null
+++ b/docs/html/images/brand/ro_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/ru_generic_rgb_wo_45.png b/docs/html/images/brand/ru_generic_rgb_wo_45.png
new file mode 100644
index 0000000..c049ddb
--- /dev/null
+++ b/docs/html/images/brand/ru_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/ru_generic_rgb_wo_60.png b/docs/html/images/brand/ru_generic_rgb_wo_60.png
new file mode 100644
index 0000000..e00c276
--- /dev/null
+++ b/docs/html/images/brand/ru_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/sk_generic_rgb_wo_45.png b/docs/html/images/brand/sk_generic_rgb_wo_45.png
new file mode 100644
index 0000000..27ce06a
--- /dev/null
+++ b/docs/html/images/brand/sk_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/sk_generic_rgb_wo_60.png b/docs/html/images/brand/sk_generic_rgb_wo_60.png
new file mode 100644
index 0000000..8591f2c
--- /dev/null
+++ b/docs/html/images/brand/sk_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/sl_generic_rgb_wo_45.png b/docs/html/images/brand/sl_generic_rgb_wo_45.png
new file mode 100644
index 0000000..115a99d
--- /dev/null
+++ b/docs/html/images/brand/sl_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/sl_generic_rgb_wo_60.png b/docs/html/images/brand/sl_generic_rgb_wo_60.png
new file mode 100644
index 0000000..37c2e52
--- /dev/null
+++ b/docs/html/images/brand/sl_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/sr_generic_rgb_wo_45.png b/docs/html/images/brand/sr_generic_rgb_wo_45.png
new file mode 100644
index 0000000..86dba47
--- /dev/null
+++ b/docs/html/images/brand/sr_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/sr_generic_rgb_wo_60.png b/docs/html/images/brand/sr_generic_rgb_wo_60.png
new file mode 100644
index 0000000..67806da
--- /dev/null
+++ b/docs/html/images/brand/sr_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/sv_generic_rgb_wo_45.png b/docs/html/images/brand/sv_generic_rgb_wo_45.png
new file mode 100644
index 0000000..fb390d8
--- /dev/null
+++ b/docs/html/images/brand/sv_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/sv_generic_rgb_wo_60.png b/docs/html/images/brand/sv_generic_rgb_wo_60.png
new file mode 100644
index 0000000..e83dce7
--- /dev/null
+++ b/docs/html/images/brand/sv_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/sw_generic_rgb_wo_45.png b/docs/html/images/brand/sw_generic_rgb_wo_45.png
new file mode 100644
index 0000000..c7deecc
--- /dev/null
+++ b/docs/html/images/brand/sw_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/sw_generic_rgb_wo_60.png b/docs/html/images/brand/sw_generic_rgb_wo_60.png
new file mode 100644
index 0000000..9c0d057
--- /dev/null
+++ b/docs/html/images/brand/sw_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/th_generic_rgb_wo_45.png b/docs/html/images/brand/th_generic_rgb_wo_45.png
new file mode 100644
index 0000000..803b6c5
--- /dev/null
+++ b/docs/html/images/brand/th_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/th_generic_rgb_wo_60.png b/docs/html/images/brand/th_generic_rgb_wo_60.png
new file mode 100644
index 0000000..6e36e02
--- /dev/null
+++ b/docs/html/images/brand/th_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/tr_generic_rgb_wo_45.png b/docs/html/images/brand/tr_generic_rgb_wo_45.png
new file mode 100644
index 0000000..baa8394
--- /dev/null
+++ b/docs/html/images/brand/tr_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/tr_generic_rgb_wo_60.png b/docs/html/images/brand/tr_generic_rgb_wo_60.png
new file mode 100644
index 0000000..63fa31f
--- /dev/null
+++ b/docs/html/images/brand/tr_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/uk_generic_rgb_wo_45.png b/docs/html/images/brand/uk_generic_rgb_wo_45.png
new file mode 100644
index 0000000..68c111f
--- /dev/null
+++ b/docs/html/images/brand/uk_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/uk_generic_rgb_wo_60.png b/docs/html/images/brand/uk_generic_rgb_wo_60.png
new file mode 100644
index 0000000..918d70a
--- /dev/null
+++ b/docs/html/images/brand/uk_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/vi_generic_rgb_wo_45.png b/docs/html/images/brand/vi_generic_rgb_wo_45.png
new file mode 100644
index 0000000..e39d00a
--- /dev/null
+++ b/docs/html/images/brand/vi_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/vi_generic_rgb_wo_60.png b/docs/html/images/brand/vi_generic_rgb_wo_60.png
new file mode 100644
index 0000000..ba1e9a0
--- /dev/null
+++ b/docs/html/images/brand/vi_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/zh-cn_generic_rgb_wo_45.png b/docs/html/images/brand/zh-cn_generic_rgb_wo_45.png
new file mode 100644
index 0000000..c7748de
--- /dev/null
+++ b/docs/html/images/brand/zh-cn_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/zh-cn_generic_rgb_wo_60.png b/docs/html/images/brand/zh-cn_generic_rgb_wo_60.png
new file mode 100644
index 0000000..0a0f91a
--- /dev/null
+++ b/docs/html/images/brand/zh-cn_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/zh-hk_generic_rgb_wo_45.png b/docs/html/images/brand/zh-hk_generic_rgb_wo_45.png
new file mode 100644
index 0000000..c3d064c
--- /dev/null
+++ b/docs/html/images/brand/zh-hk_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/zh-hk_generic_rgb_wo_60.png b/docs/html/images/brand/zh-hk_generic_rgb_wo_60.png
new file mode 100644
index 0000000..2b072de
--- /dev/null
+++ b/docs/html/images/brand/zh-hk_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/zh-tw_generic_rgb_wo_45.png b/docs/html/images/brand/zh-tw_generic_rgb_wo_45.png
new file mode 100644
index 0000000..7bb2b09
--- /dev/null
+++ b/docs/html/images/brand/zh-tw_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/zh-tw_generic_rgb_wo_60.png b/docs/html/images/brand/zh-tw_generic_rgb_wo_60.png
new file mode 100644
index 0000000..0797c84b
--- /dev/null
+++ b/docs/html/images/brand/zh-tw_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/zu_generic_rgb_wo_45.png b/docs/html/images/brand/zu_generic_rgb_wo_45.png
new file mode 100644
index 0000000..1e9f7c7
--- /dev/null
+++ b/docs/html/images/brand/zu_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/zu_generic_rgb_wo_60.png b/docs/html/images/brand/zu_generic_rgb_wo_60.png
new file mode 100644
index 0000000..09f521b
--- /dev/null
+++ b/docs/html/images/brand/zu_generic_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/training/basics/activity-lifecycle/recreating.jd b/docs/html/training/basics/activity-lifecycle/recreating.jd
index 1a65e71..71fd5dd 100644
--- a/docs/html/training/basics/activity-lifecycle/recreating.jd
+++ b/docs/html/training/basics/activity-lifecycle/recreating.jd
@@ -126,7 +126,7 @@
state from the {@link android.os.Bundle} that the system
passes your activity. Both the {@link android.app.Activity#onCreate onCreate()} and {@link
android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} callback methods receive
-the same {@link android.os.Bundle} that containes the instance state information.</p>
+the same {@link android.os.Bundle} that contains the instance state information.</p>
<p>Because the {@link android.app.Activity#onCreate onCreate()} method is called whether the
system is creating a new instance of your activity or recreating a previous one, you must check
diff --git a/docs/html/training/basics/activity-lifecycle/starting.jd b/docs/html/training/basics/activity-lifecycle/starting.jd
index dd17304..dce6e30 100644
--- a/docs/html/training/basics/activity-lifecycle/starting.jd
+++ b/docs/html/training/basics/activity-lifecycle/starting.jd
@@ -265,7 +265,7 @@
with the activity and your activity should perform most cleanup during {@link
android.app.Activity#onPause} and {@link android.app.Activity#onStop}. However, if your
activity includes background threads that you created during {@link
-android.app.Activity#onCreate onCreate()} or other other long-running resources that could
+android.app.Activity#onCreate onCreate()} or other long-running resources that could
potentially leak memory if not properly closed, you should kill them during {@link
android.app.Activity#onDestroy}.</p>
diff --git a/docs/html/training/basics/data-storage/shared-preferences.jd b/docs/html/training/basics/data-storage/shared-preferences.jd
index 67f45cb..099da67 100644
--- a/docs/html/training/basics/data-storage/shared-preferences.jd
+++ b/docs/html/training/basics/data-storage/shared-preferences.jd
@@ -115,7 +115,7 @@
<pre>
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
-long default = getResources().getInteger(R.string.saved_high_score_default));
-long highScore = sharedPref.getInt(getString(R.string.saved_high_score), default);
+int defaultValue = getResources().getInteger(R.string.saved_high_score_default);
+long highScore = sharedPref.getInt(getString(R.string.saved_high_score), defaultValue);
</pre>
diff --git a/docs/html/training/basics/network-ops/xml.jd b/docs/html/training/basics/network-ops/xml.jd
index b148257..0ea696d 100644
--- a/docs/html/training/basics/network-ops/xml.jd
+++ b/docs/html/training/basics/network-ops/xml.jd
@@ -551,5 +551,5 @@
conn.setDoInput(true);
// Starts the query
conn.connect();
- InputStream stream = conn.getInputStream();
+ return conn.getInputStream();
}</pre>
diff --git a/docs/html/training/basics/supporting-devices/screens.jd b/docs/html/training/basics/supporting-devices/screens.jd
index 8697cd5..1114f21 100644
--- a/docs/html/training/basics/supporting-devices/screens.jd
+++ b/docs/html/training/basics/supporting-devices/screens.jd
@@ -108,7 +108,7 @@
<p>By default, the <code>layout/main.xml</code> file is used for portrait orientation.</p>
-<p>If you want a provide a special layout for landscape, including while on large screens, then
+<p>If you want to provide a special layout for landscape, including while on large screens, then
you need to use both the <code>large</code> and <code>land</code> qualifier:</p>
<pre class="classic no-pretty-print">
diff --git a/docs/html/training/custom-views/index.jd b/docs/html/training/custom-views/index.jd
index 0661c05..cec75b4 100644
--- a/docs/html/training/custom-views/index.jd
+++ b/docs/html/training/custom-views/index.jd
@@ -17,12 +17,12 @@
<h2>You should also read</h2>
<ul>
- <li><a href="{@docRoot}/guide/topics/ui/custom-components.html">Custom Components</a>
+ <li><a href="{@docRoot}guide/topics/ui/custom-components.html">Custom Components</a>
</li>
- <li><a href="{@docRoot}/guide/topics/ui/ui-events.html">Input Events</a></li>
- <li><a href="{@docRoot}/guide/topics/graphics/prop-animation.html">Property
+ <li><a href="{@docRoot}guide/topics/ui/ui-events.html">Input Events</a></li>
+ <li><a href="{@docRoot}guide/topics/graphics/prop-animation.html">Property
Animation</a></li>
- <li><a href="{@docRoot}/guide/topics/graphics/hardware-accel.html">Hardware
+ <li><a href="{@docRoot}guide/topics/graphics/hardware-accel.html">Hardware
Acceleration</a></li>
<li><a href="{@docRoot}guide/topics/ui/accessibility/index.html">
Accessibility</a> developer guide</li>
diff --git a/docs/html/training/managing-audio/volume-playback.jd b/docs/html/training/managing-audio/volume-playback.jd
index 76abbb6..be0f583 100644
--- a/docs/html/training/managing-audio/volume-playback.jd
+++ b/docs/html/training/managing-audio/volume-playback.jd
@@ -153,4 +153,4 @@
UI.</p>
<p>A better approach is to register and unregister the media button event receiver when your
-application gains and losses the audio focus. This is covered in detail in the next lesson.</p>
+application gains and loses the audio focus. This is covered in detail in the next lesson.</p>
diff --git a/docs/html/training/multiple-apks/texture.jd b/docs/html/training/multiple-apks/texture.jd
index e4ea72b..c49cc95 100644
--- a/docs/html/training/multiple-apks/texture.jd
+++ b/docs/html/training/multiple-apks/texture.jd
@@ -90,8 +90,8 @@
<tbody>
<tr>
<td class="blueCell">ETC1</td>
- <td class="greenCell">ATI</td>
- <td class="redCell">PowerVR</td>
+ <td class="redCell">ATI</td>
+ <td class="greenCell">PowerVR</td>
</tr>
</tbody>
</table>
diff --git a/docs/html/training/sharing/send.jd b/docs/html/training/sharing/send.jd
index 741c017..9cb8eac 100644
--- a/docs/html/training/sharing/send.jd
+++ b/docs/html/training/sharing/send.jd
@@ -32,7 +32,7 @@
<p>When you construct an intent, you must specify the action you want the intent to "trigger."
Android defines several actions, including {@link android.content.Intent#ACTION_SEND} which, as
you can probably guess, indicates that the intent is sending data from one activity to another,
-even across process boundaries. To send data to another activity, all you need to do is speicify
+even across process boundaries. To send data to another activity, all you need to do is specify
the data and its type, the system will identify compatible receiving activities and display them
to the user (if there are multiple options) or immediately start the activity (if there is only
one option). Similarly, you can advertise the data types that your activities support receiving
@@ -95,7 +95,7 @@
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
-startActivity(<strong>Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)</strong>);
+startActivity(<strong>Intent.createChooser(sendIntent, getResources().getText(R.string.send_to))</strong>);
</pre>
<p>The resulting dialog is shown in figure 1.</p>
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 900720a..fa115ff 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -240,10 +240,10 @@
rsnElementGetSubElements(mContext, id, IDs, names, arraySizes);
}
- native int rsnTypeCreate(int con, int eid, int x, int y, int z, boolean mips, boolean faces);
- synchronized int nTypeCreate(int eid, int x, int y, int z, boolean mips, boolean faces) {
+ native int rsnTypeCreate(int con, int eid, int x, int y, int z, boolean mips, boolean faces, int yuv);
+ synchronized int nTypeCreate(int eid, int x, int y, int z, boolean mips, boolean faces, int yuv) {
validate();
- return rsnTypeCreate(mContext, eid, x, y, z, mips, faces);
+ return rsnTypeCreate(mContext, eid, x, y, z, mips, faces, yuv);
}
native void rsnTypeGetNativeData(int con, int id, int[] typeData);
synchronized void nTypeGetNativeData(int id, int[] typeData) {
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index 93d8b4b..cb12594 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -18,6 +18,8 @@
import java.lang.reflect.Field;
+
+import android.graphics.ImageFormat;
import android.util.Log;
/**
@@ -208,6 +210,7 @@
int mDimZ;
boolean mDimMipmaps;
boolean mDimFaces;
+ int mYuv;
Element mElement;
@@ -263,6 +266,25 @@
return this;
}
+ /**
+ * @hide
+ *
+ * only NV21, YV12. Enums from ImageFormat
+ */
+ public Builder setYuvFormat(int yuvFormat) {
+ switch (yuvFormat) {
+ case android.graphics.ImageFormat.NV21:
+ case android.graphics.ImageFormat.YV12:
+ break;
+
+ default:
+ throw new RSIllegalArgumentException("Only NV21 and YV12 are supported..");
+ }
+
+ mYuv = yuvFormat;
+ return this;
+ }
+
/**
* Validate structure and create a new type.
@@ -289,8 +311,14 @@
}
}
+ if (mYuv != 0) {
+ if ((mDimZ != 0) || mDimFaces || mDimMipmaps) {
+ throw new RSInvalidStateException("YUV only supports basic 2D.");
+ }
+ }
+
int id = mRS.nTypeCreate(mElement.getID(mRS),
- mDimX, mDimY, mDimZ, mDimMipmaps, mDimFaces);
+ mDimX, mDimY, mDimZ, mDimMipmaps, mDimFaces, mYuv);
Type t = new Type(id, mRS);
t.mElement = mElement;
t.mDimX = mDimX;
@@ -298,6 +326,7 @@
t.mDimZ = mDimZ;
t.mDimMipmaps = mDimMipmaps;
t.mDimFaces = mDimFaces;
+ t.mDimYuv = mYuv;
t.calcElementCount();
return t;
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 75c7903..54413b4 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -427,12 +427,12 @@
static int
nTypeCreate(JNIEnv *_env, jobject _this, RsContext con, RsElement eid,
- jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces)
+ jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces, jint yuv)
{
- LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i)",
- con, eid, dimx, dimy, dimz, mips, faces);
+ LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
+ con, eid, dimx, dimy, dimz, mips, faces, yuv);
- jint id = (jint)rsTypeCreate(con, (RsElement)eid, dimx, dimy, dimz, mips, faces);
+ jint id = (jint)rsTypeCreate(con, (RsElement)eid, dimx, dimy, dimz, mips, faces, yuv);
return (jint)id;
}
@@ -1454,7 +1454,7 @@
{"rsnElementGetNativeData", "(II[I)V", (void*)nElementGetNativeData },
{"rsnElementGetSubElements", "(II[I[Ljava/lang/String;[I)V", (void*)nElementGetSubElements },
-{"rsnTypeCreate", "(IIIIIZZ)I", (void*)nTypeCreate },
+{"rsnTypeCreate", "(IIIIIZZI)I", (void*)nTypeCreate },
{"rsnTypeGetNativeData", "(II[I)V", (void*)nTypeGetNativeData },
{"rsnAllocationCreateTyped", "(IIIII)I", (void*)nAllocationCreateTyped },
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 902c82f..e490151 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -37,7 +37,7 @@
// 2 triangles per patch, 3 vertices per triangle
uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 2 * 3;
mVertices = new TextureVertex[maxVertices];
- mUploaded = false;
+ mAllocatedVerticesCount = 0;
verticesCount = 0;
hasEmptyQuads = emptyQuads > 0;
@@ -68,38 +68,37 @@
memcpy(mYDivs, yDivs, mYCount * sizeof(int32_t));
}
-void Patch::copy(const int32_t* yDivs) {
- memcpy(mYDivs, yDivs, mYCount * sizeof(int32_t));
-}
-
void Patch::updateColorKey(const uint32_t colorKey) {
mColorKey = colorKey;
}
-bool Patch::matches(const int32_t* xDivs, const int32_t* yDivs, const uint32_t colorKey) {
+bool Patch::matches(const int32_t* xDivs, const int32_t* yDivs,
+ const uint32_t colorKey, const int8_t emptyQuads) {
+
+ bool matches = true;
+
+ if (mEmptyQuads != emptyQuads) {
+ mEmptyQuads = emptyQuads;
+ hasEmptyQuads = emptyQuads > 0;
+ matches = false;
+ }
+
if (mColorKey != colorKey) {
updateColorKey(colorKey);
- copy(xDivs, yDivs);
- return false;
+ matches = false;
}
- for (uint32_t i = 0; i < mXCount; i++) {
- if (mXDivs[i] != xDivs[i]) {
- // The Y divs may or may not match, copy everything
- copy(xDivs, yDivs);
- return false;
- }
+ if (memcmp(mXDivs, xDivs, mXCount * sizeof(int32_t))) {
+ memcpy(mXDivs, xDivs, mXCount * sizeof(int32_t));
+ matches = false;
}
- for (uint32_t i = 0; i < mYCount; i++) {
- if (mYDivs[i] != yDivs[i]) {
- // We know all the X divs match, copy only Y divs
- copy(yDivs);
- return false;
- }
+ if (memcmp(mYDivs, yDivs, mYCount * sizeof(int32_t))) {
+ memcpy(mYDivs, yDivs, mYCount * sizeof(int32_t));
+ matches = false;
}
- return true;
+ return matches;
}
///////////////////////////////////////////////////////////////////////////////
@@ -203,10 +202,10 @@
if (verticesCount > 0) {
Caches& caches = Caches::getInstance();
caches.bindMeshBuffer(meshBuffer);
- if (!mUploaded) {
+ if (mAllocatedVerticesCount < verticesCount) {
glBufferData(GL_ARRAY_BUFFER, sizeof(TextureVertex) * verticesCount,
mVertices, GL_DYNAMIC_DRAW);
- mUploaded = true;
+ mAllocatedVerticesCount = verticesCount;
} else {
glBufferSubData(GL_ARRAY_BUFFER, 0,
sizeof(TextureVertex) * verticesCount, mVertices);
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 0518d91..cab0e54 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -45,7 +45,7 @@
* indices to render the vertices.
*/
struct Patch {
- Patch(const uint32_t xCount, const uint32_t yCount, const int8_t emptyQuads = 0);
+ Patch(const uint32_t xCount, const uint32_t yCount, const int8_t emptyQuads);
~Patch();
void updateVertices(const float bitmapWidth, const float bitmapHeight,
@@ -53,7 +53,8 @@
void updateColorKey(const uint32_t colorKey);
void copy(const int32_t* xDivs, const int32_t* yDivs);
- bool matches(const int32_t* xDivs, const int32_t* yDivs, const uint32_t colorKey);
+ bool matches(const int32_t* xDivs, const int32_t* yDivs,
+ const uint32_t colorKey, const int8_t emptyQuads);
GLuint meshBuffer;
uint32_t verticesCount;
@@ -62,7 +63,7 @@
private:
TextureVertex* mVertices;
- bool mUploaded;
+ uint32_t mAllocatedVerticesCount;
int32_t* mXDivs;
int32_t* mYDivs;
@@ -72,8 +73,6 @@
uint32_t mYCount;
int8_t mEmptyQuads;
- void copy(const int32_t* yDivs);
-
void generateRow(TextureVertex*& vertex, float y1, float y2,
float v1, float v2, float stretchX, float rescaleX,
float width, float bitmapWidth, uint32_t& quadCount);
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index 9702c3d..8ee8f5c 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -97,7 +97,7 @@
}
mCache.add(description, mesh);
- } else if (!mesh->matches(xDivs, yDivs, colorKey)) {
+ } else if (!mesh->matches(xDivs, yDivs, colorKey, transparentQuads)) {
PATCH_LOGD("Patch mesh does not match, refreshing vertices");
mesh->updateVertices(bitmapWidth, bitmapHeight, 0.0f, 0.0f, pixelWidth, pixelHeight);
}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index f663e0a..c353ec6 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -47,7 +47,7 @@
Location getLastLocation(in LocationRequest request, String packageName);
- boolean addGpsStatusListener(IGpsStatusListener listener);
+ boolean addGpsStatusListener(IGpsStatusListener listener, String packageName);
void removeGpsStatusListener(IGpsStatusListener listener);
boolean geocoderIsPresent();
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 5a2f71b..0b9286e 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1461,7 +1461,7 @@
}
try {
GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener);
- result = mService.addGpsStatusListener(transport);
+ result = mService.addGpsStatusListener(transport, mContext.getPackageName());
if (result) {
mGpsStatusListeners.put(listener, transport);
}
@@ -1507,7 +1507,7 @@
}
try {
GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener);
- result = mService.addGpsStatusListener(transport);
+ result = mService.addGpsStatusListener(transport, mContext.getPackageName());
if (result) {
mNmeaListeners.put(listener, transport);
}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index fbbcb0a..7768a61 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -958,7 +958,9 @@
// If the rowId of the inserted file is needed, it gets inserted immediately,
// bypassing the bulk inserter.
if (inserter == null || needToSetSettings) {
- inserter.flushAll();
+ if (inserter != null) {
+ inserter.flushAll();
+ }
result = mMediaProvider.insert(tableUri, values);
} else if (entry.mFormat == MtpConstants.FORMAT_ASSOCIATION) {
inserter.insertwithPriority(tableUri, values);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaRecorderStressTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaRecorderStressTestRunner.java
index 95e7b5e..5c74552 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaRecorderStressTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaRecorderStressTestRunner.java
@@ -33,18 +33,16 @@
// the test must be supported by the corresponding camera.
public static int mCameraId = 0;
public static int mProfileQuality = CamcorderProfile.QUALITY_HIGH;
- public static CamcorderProfile profile =
- CamcorderProfile.get(mCameraId, mProfileQuality);
-
- public static int mIterations = 100;
+ public static CamcorderProfile profile = CamcorderProfile.get(mCameraId, mProfileQuality);
+ public static int mIterations = 15;
public static int mVideoEncoder = profile.videoCodec;
- public static int mAudioEncdoer = profile.audioCodec;
+ public static int mAudioEncoder = profile.audioCodec;
public static int mFrameRate = profile.videoFrameRate;
public static int mVideoWidth = profile.videoFrameWidth;
public static int mVideoHeight = profile.videoFrameHeight;
public static int mBitRate = profile.videoBitRate;
public static boolean mRemoveVideo = true;
- public static int mDuration = 10 * 1000; // 10 seconds
+ public static int mDuration = 60 * 1000; // 60 seconds
public static int mTimeLapseDuration = 180 * 1000; // 3 minutes
public static double mCaptureRate = 0.5; // 2 sec timelapse interval
@@ -64,41 +62,41 @@
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
String iterations = (String) icicle.get("iterations");
- String video_encoder = (String) icicle.get("video_encoder");
- String audio_encoder = (String) icicle.get("audio_encoder");
- String frame_rate = (String) icicle.get("frame_rate");
- String video_width = (String) icicle.get("video_width");
- String video_height = (String) icicle.get("video_height");
- String bit_rate = (String) icicle.get("bit_rate");
- String record_duration = (String) icicle.get("record_duration");
- String remove_videos = (String) icicle.get("remove_videos");
+ String videoEncoder = (String) icicle.get("video_encoder");
+ String audioEncoder = (String) icicle.get("audio_encoder");
+ String frameRate = (String) icicle.get("frame_rate");
+ String videoWidth = (String) icicle.get("video_width");
+ String videoHeight = (String) icicle.get("video_height");
+ String bitRate = (String) icicle.get("bit_rate");
+ String recordDuration = (String) icicle.get("record_duration");
+ String removeVideos = (String) icicle.get("remove_videos");
if (iterations != null ) {
mIterations = Integer.parseInt(iterations);
}
- if ( video_encoder != null) {
- mVideoEncoder = Integer.parseInt(video_encoder);
+ if (videoEncoder != null) {
+ mVideoEncoder = Integer.parseInt(videoEncoder);
}
- if ( audio_encoder != null) {
- mAudioEncdoer = Integer.parseInt(audio_encoder);
+ if (audioEncoder != null) {
+ mAudioEncoder = Integer.parseInt(audioEncoder);
}
- if (frame_rate != null) {
- mFrameRate = Integer.parseInt(frame_rate);
+ if (frameRate != null) {
+ mFrameRate = Integer.parseInt(frameRate);
}
- if (video_width != null) {
- mVideoWidth = Integer.parseInt(video_width);
+ if (videoWidth != null) {
+ mVideoWidth = Integer.parseInt(videoWidth);
}
- if (video_height != null) {
- mVideoHeight = Integer.parseInt(video_height);
+ if (videoHeight != null) {
+ mVideoHeight = Integer.parseInt(videoHeight);
}
- if (bit_rate != null) {
- mBitRate = Integer.parseInt(bit_rate);
+ if (bitRate != null) {
+ mBitRate = Integer.parseInt(bitRate);
}
- if (record_duration != null) {
- mDuration = Integer.parseInt(record_duration);
+ if (recordDuration != null) {
+ mDuration = Integer.parseInt(recordDuration);
}
- if (remove_videos != null) {
- if (remove_videos.compareTo("true") == 0) {
+ if (removeVideos != null) {
+ if (removeVideos.compareTo("true") == 0) {
mRemoveVideo = true;
} else {
mRemoveVideo = false;
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 ab9e36c3..ed1d8fc 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java
@@ -28,6 +28,7 @@
import java.io.Writer;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+import java.util.List;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
@@ -44,7 +45,7 @@
import junit.framework.Assert;
/**
- * Junit / Instrumentation test case for the camera zoom api
+ * Junit / Instrumentation test case for the camera zoom and scene mode APIs
*
* adb shell am instrument
* -e class com.android.mediaframeworktest.stress.CameraStressTest
@@ -54,18 +55,22 @@
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 long WAIT_TIMEOUT = 10 * 1000; // 10 seconds
private static final long WAIT_ZOOM_ANIMATION = 5 * 1000; // 5 seconds
- private static final String CAMERA_STRESS_OUTPUT =
- "/sdcard/cameraStressOutput.txt";
- private static final int CAMERA_ID = 0;
+ 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 Handler mHandler;
+ private Writer mOutput;
+
public CameraStressTest() {
super("com.android.mediaframeworktest", MediaFrameworkTest.class);
}
@@ -89,6 +94,20 @@
}
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));
+ mOutput = new BufferedWriter(new FileWriter(stressOutFile, true));
+ mOutput.write(this.getName() + ":\n");
}
@Override
@@ -105,6 +124,9 @@
mLooperThread = null;
}
+ mOutput.write("\n\n");
+ mOutput.close();
+
super.tearDown();
}
@@ -127,9 +149,7 @@
private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
public void onError(int error, android.hardware.Camera camera) {
- if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) {
- assertTrue("Camera test mediaserver died", false);
- }
+ fail(String.format("Camera error, code: %d", error));
}
}
@@ -154,49 +174,76 @@
try {
Log.v(TAG, "JPEG picture taken");
- fos = new FileOutputStream(String.format("%s/zoom-test-%d.jpg",
- Environment.getExternalStorageDirectory(), System.currentTimeMillis()));
+ 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.v(TAG, "File not found: " + e.toString());
- }
- catch (IOException e) {
- Log.v(TAG, "Error accessing file: " + e.toString());
- }
- finally {
+ } 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.v(TAG, "Error closing file: " + e.toString());
+ } catch (IOException e) {
+ Log.e(TAG, "Error closing file: " + e.toString());
}
}
}
};
// Helper method for cleaning up pics taken during testStressCameraZoom
- private void cleanupZoomImages() {
+ private void cleanupStressTestImages() {
try {
- File sdcard = Environment.getExternalStorageDirectory();
+ 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("zoom-test-");
+ return name.startsWith(CAMERA_STRESS_IMAGES_PREFIX);
}
};
- zoomImages = sdcard.listFiles(filter);
+ zoomImages = stressImagesDirectory.listFiles(filter);
for (File f : zoomImages) {
f.delete();
}
+ } catch (SecurityException e) {
+ Log.e(TAG, "Security manager access violation: " + e.toString());
}
- catch (SecurityException e) {
- Log.v(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());
}
}
@@ -205,14 +252,11 @@
public void testStressCameraZoom() throws Exception {
SurfaceHolder mSurfaceHolder;
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
- File stressOutFile = new File(CAMERA_STRESS_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
- output.write("Camera zoom stress:\n");
- output.write("Total number of loops: " + NUMBER_OF_ZOOM_LOOPS + "\n");
+ mOutput.write("Total number of loops: " + NUMBER_OF_ZOOM_LOOPS + "\n");
try {
Log.v(TAG, "Start preview");
- output.write("No of loop: ");
+ mOutput.write("No of loop: ");
mCamera = Camera.open(CAMERA_ID);
Camera.Parameters params = mCamera.getParameters();
@@ -220,9 +264,8 @@
if (!params.isSmoothZoomSupported() && !params.isZoomSupported()) {
Log.v(TAG, "Device camera does not support zoom");
- assertTrue("Camera zoom stress test", false);
- }
- else {
+ fail("Camera zoom stress test failed");
+ } else {
Log.v(TAG, "Device camera does support zoom");
int nextZoomLevel = 0;
@@ -235,11 +278,7 @@
}
});
- mCamera.setErrorCallback(mCameraErrorCallback);
- mCamera.setPreviewDisplay(mSurfaceHolder);
- mCamera.startPreview();
- Thread.sleep(WAIT_GENERIC);
-
+ startCameraPreview(mSurfaceHolder);
params = mCamera.getParameters();
int currentZoomLevel = params.getZoom();
@@ -250,8 +289,7 @@
if (params.isSmoothZoomSupported()) {
mCamera.startSmoothZoom(nextZoomLevel);
- }
- else {
+ } else {
params.setZoom(nextZoomLevel);
mCamera.setParameters(params);
}
@@ -259,23 +297,66 @@
// sleep allows for zoom animation to finish
Thread.sleep(WAIT_ZOOM_ANIMATION);
+ capturePhoto();
- // take picture
- mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
- Thread.sleep(WAIT_GENERIC);
- mCamera.stopPreview();
- mCamera.release();
- output.write(" ," + i);
+ 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");
+ }
+ }
- cleanupZoomImages();
+ // Test case for stressing the camera scene mode feature
+ @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();
+ List<String> supportedSceneModes = params.getSupportedSceneModes();
+ assertNotNull("No scene modes supported", supportedSceneModes);
+
+ mOutput.write("Total number of loops: " +
+ (NUMBER_OF_SCENE_MODE_LOOPS * supportedSceneModes.size()) + "\n");
+ Log.v(TAG, "Start preview");
+ mOutput.write("No of loop: ");
+
+ for (int i = 0; i < supportedSceneModes.size(); i++) {
+ for (int j = 0; j < NUMBER_OF_SCENE_MODE_LOOPS; j++) {
+ runOnLooper(new Runnable() {
+ @Override
+ public void run() {
+ mCamera = Camera.open(CAMERA_ID);
+ }
+ });
+
+ startCameraPreview(mSurfaceHolder);
+ Log.v(TAG, "Setting mode to " + supportedSceneModes.get(i));
+ params.setSceneMode(supportedSceneModes.get(i));
+ mCamera.setParameters(params);
+ capturePhoto();
+
+ 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();
+ } catch (Exception e) {
+ Log.e(TAG, e.toString());
+ fail("Camera scene mode test Exception");
}
- catch (Exception e) {
- assertTrue("Camera zoom stress test Exception", false);
- Log.v(TAG, e.toString());
- }
- output.write("\n\n");
- output.close();
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
index 6995c60..6eb9891 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
@@ -31,6 +31,7 @@
import android.media.CamcorderProfile;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
+import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.test.ActivityInstrumentationTestCase2;
@@ -48,26 +49,26 @@
private MediaRecorder mRecorder;
private Camera mCamera;
+ private static final int CAMERA_ID = 0;
private static final int NUMBER_OF_CAMERA_STRESS_LOOPS = 100;
private static final int NUMBER_OF_RECORDER_STRESS_LOOPS = 100;
private static final int NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS = 50;
private static final int NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER = 200;
private static final int NUMBER_OF_TIME_LAPSE_LOOPS = 25;
private static final int TIME_LAPSE_PLAYBACK_WAIT_TIME = 5* 1000; // 5 seconds
+ private static final int USE_TEST_RUNNER_PROFILE = -1;
+ private static final long WAIT_TIMEOUT = 10 * 1000; // 10 seconds
private static final long WAIT_TIME_CAMERA_TEST = 3 * 1000; // 3 seconds
private static final long WAIT_TIME_RECORDER_TEST = 6 * 1000; // 6 seconds
- private static final String OUTPUT_FILE = "/sdcard/temp";
private static final String OUTPUT_FILE_EXT = ".3gp";
- private static final String MEDIA_STRESS_OUTPUT =
- "/sdcard/mediaStressOutput.txt";
- private static final int CAMERA_ID = 0;
+ private static final String MEDIA_STRESS_OUTPUT = "mediaStressOutput.txt";
private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
private final RecorderErrorCallback mRecorderErrorCallback = new RecorderErrorCallback();
- private final static int WAIT_TIMEOUT = 10 * 1000; // 10 seconds
- private Thread mLooperThread;
private Handler mHandler;
+ private Thread mLooperThread;
+ private Writer mOutput;
public MediaRecorderStressTest() {
super("com.android.mediaframeworktest", MediaFrameworkTest.class);
@@ -95,6 +96,11 @@
Thread.sleep(2000);
getActivity();
super.setUp();
+
+ File stressOutFile = new File(String.format("%s/%s",
+ Environment.getExternalStorageDirectory(), MEDIA_STRESS_OUTPUT));
+ mOutput = new BufferedWriter(new FileWriter(stressOutFile, true));
+ mOutput.write(this.getName() + "\n");
}
@Override
@@ -110,7 +116,8 @@
}
mLooperThread = null;
}
-
+ mOutput.write("\n\n");
+ mOutput.close();
super.tearDown();
}
@@ -133,16 +140,13 @@
private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
public void onError(int error, android.hardware.Camera camera) {
- if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) {
- assertTrue("Camera test mediaserver died", false);
- }
+ fail(String.format("Camera error, code: %d", error));
}
}
private final class RecorderErrorCallback implements MediaRecorder.OnErrorListener {
public void onError(MediaRecorder mr, int what, int extra) {
- // fail the test case no matter what error come up
- assertTrue("mediaRecorder error", false);
+ fail(String.format("Media recorder error, code: %d\textra: %d", what, extra));
}
}
@@ -151,14 +155,11 @@
public void testStressCamera() throws Exception {
SurfaceHolder mSurfaceHolder;
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
- File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
- output.write("Camera start preview stress:\n");
- output.write("Total number of loops:" +
- NUMBER_OF_CAMERA_STRESS_LOOPS + "\n");
+ Log.v(TAG, "Camera start preview stress test");
+ mOutput.write("Total number of loops:" + NUMBER_OF_CAMERA_STRESS_LOOPS + "\n");
try {
Log.v(TAG, "Start preview");
- output.write("No of loop: ");
+ mOutput.write("No of loop: ");
for (int i = 0; i< NUMBER_OF_CAMERA_STRESS_LOOPS; i++) {
runOnLooper(new Runnable() {
@@ -173,29 +174,27 @@
Thread.sleep(WAIT_TIME_CAMERA_TEST);
mCamera.stopPreview();
mCamera.release();
- output.write(" ," + i);
+ if (i == 0) {
+ mOutput.write(i + 1);
+ } else {
+ mOutput.write(String.format(", %d", (i + 1)));
+ }
}
} catch (Exception e) {
- assertTrue("CameraStressTest", false);
- Log.v(TAG, e.toString());
+ Log.e(TAG, e.toString());
+ fail("Camera startup preview stress test");
}
- output.write("\n\n");
- output.close();
}
//Test case for stressing the camera preview.
@LargeTest
public void testStressRecorder() throws Exception {
- String filename;
SurfaceHolder mSurfaceHolder;
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
- File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
- output.write("H263 video record- reset after prepare Stress test\n");
- output.write("Total number of loops:" +
- NUMBER_OF_RECORDER_STRESS_LOOPS + "\n");
+ Log.v(TAG, "H263 video record: reset after prepare Stress test");
+ mOutput.write("Total number of loops:" + NUMBER_OF_RECORDER_STRESS_LOOPS + "\n");
try {
- output.write("No of loop: ");
+ mOutput.write("No of loop: ");
Log.v(TAG, "Start preview");
for (int i = 0; i < NUMBER_OF_RECORDER_STRESS_LOOPS; i++) {
runOnLooper(new Runnable() {
@@ -205,12 +204,15 @@
}
});
Log.v(TAG, "counter = " + i);
- filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
- Log.v(TAG, filename);
+ String fileName = String.format("%s/temp%d%s",
+ Environment.getExternalStorageDirectory(),
+ i, OUTPUT_FILE_EXT);
+
+ Log.v(TAG, fileName);
mRecorder.setOnErrorListener(mRecorderErrorCallback);
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setOutputFile(filename);
+ mRecorder.setOutputFile(fileName);
mRecorder.setVideoFrameRate(MediaRecorderStressTestRunner.mFrameRate);
mRecorder.setVideoSize(176,144);
Log.v(TAG, "setEncoder");
@@ -224,30 +226,29 @@
Thread.sleep(WAIT_TIME_RECORDER_TEST);
mRecorder.reset();
mRecorder.release();
- output.write(", " + i);
+ if (i == 0) {
+ mOutput.write(i + 1);
+ } else {
+ mOutput.write(String.format(", %d", (i + 1)));
+ }
}
} catch (Exception e) {
- assertTrue("Recorder Stress test", false);
- Log.v(TAG, e.toString());
+ Log.e(TAG, e.toString());
+ fail("H263 video recording stress test");
}
- output.write("\n\n");
- output.close();
}
//Stress test case for switching camera and video recorder preview.
@LargeTest
public void testStressCameraSwitchRecorder() throws Exception {
- String filename;
SurfaceHolder mSurfaceHolder;
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
- File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
- output.write("Camera and video recorder preview switching\n");
- output.write("Total number of loops:"
- + NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER + "\n");
+ Log.v(TAG, "Camera and video recorder preview switching");
+ mOutput.write("Total number of loops: " +
+ NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER + "\n");
try {
Log.v(TAG, "Start preview");
- output.write("No of loop: ");
+ mOutput.write("No of loop: ");
for (int i = 0; i < NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER; i++) {
runOnLooper(new Runnable() {
@Override
@@ -263,8 +264,10 @@
mCamera.release();
mCamera = null;
Log.v(TAG, "release camera");
- filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
- Log.v(TAG, filename);
+ String fileName = String.format("%s/temp%d%s",
+ Environment.getExternalStorageDirectory(),
+ i, OUTPUT_FILE_EXT);
+ Log.v(TAG, fileName);
runOnLooper(new Runnable() {
@Override
public void run() {
@@ -274,7 +277,7 @@
mRecorder.setOnErrorListener(mRecorderErrorCallback);
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setOutputFile(filename);
+ mRecorder.setOutputFile(fileName);
mRecorder.setVideoFrameRate(MediaRecorderStressTestRunner.mFrameRate);
mRecorder.setVideoSize(176,144);
Log.v(TAG, "Media recorder setEncoder");
@@ -287,117 +290,167 @@
Thread.sleep(WAIT_TIME_CAMERA_TEST);
mRecorder.release();
Log.v(TAG, "release video recorder");
- output.write(", " + i);
+ if (i == 0) {
+ mOutput.write(i + 1);
+ } else {
+ mOutput.write(String.format(", %d", (i + 1)));
+ }
}
} catch (Exception e) {
- assertTrue("Camer and recorder switch mode", false);
- Log.v(TAG, e.toString());
+ Log.e(TAG, e.toString());
+ fail("Camera and recorder switch mode");
}
- output.write("\n\n");
- output.close();
}
- public void validateRecordedVideo(String recorded_file) {
+ public void validateRecordedVideo(String recordedFile) {
try {
MediaPlayer mp = new MediaPlayer();
- mp.setDataSource(recorded_file);
+ mp.setDataSource(recordedFile);
mp.prepare();
int duration = mp.getDuration();
if (duration <= 0){
- assertTrue("stressRecordAndPlayback", false);
+ fail("stressRecordAndPlayback");
}
mp.release();
} catch (Exception e) {
- assertTrue("stressRecordAndPlayback", false);
+ fail("stressRecordAndPlayback");
}
}
- public void removeRecordedVideo(String filename){
- File video = new File(filename);
- Log.v(TAG, "remove recorded video " + filename);
+ public void removeRecordedVideo(String fileName){
+ File video = new File(fileName);
+ Log.v(TAG, "remove recorded video " + fileName);
video.delete();
}
- //Stress test case for record a video and play right away.
- @LargeTest
- public void testStressRecordVideoAndPlayback() throws Exception {
- int iterations = MediaRecorderStressTestRunner.mIterations;
- int video_encoder = MediaRecorderStressTestRunner.mVideoEncoder;
- int audio_encoder = MediaRecorderStressTestRunner.mAudioEncdoer;
- int frame_rate = MediaRecorderStressTestRunner.mFrameRate;
- int video_width = MediaRecorderStressTestRunner.mVideoWidth;
- int video_height = MediaRecorderStressTestRunner.mVideoHeight;
- int bit_rate = MediaRecorderStressTestRunner.mBitRate;
- boolean remove_video = MediaRecorderStressTestRunner.mRemoveVideo;
- int record_duration = MediaRecorderStressTestRunner.mDuration;
+ // Helper method for record & playback testing with different camcorder profiles
+ private void recordVideoAndPlayback(int profile) throws Exception {
+ int iterations;
+ int recordDuration;
+ boolean removeVideo;
- String filename;
- SurfaceHolder mSurfaceHolder;
- mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
- File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
- Writer output = new BufferedWriter(
- new FileWriter(stressOutFile, true));
- output.write("Video record and play back stress test:\n");
- output.write("Total number of loops:"
- + NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS + "\n");
+ int videoEncoder;
+ int audioEncoder;
+ int frameRate;
+ int videoWidth;
+ int videoHeight;
+ int bitRate;
+
+ if (profile != USE_TEST_RUNNER_PROFILE) {
+ assertTrue(String.format("Camera doesn't support profile %d", profile),
+ CamcorderProfile.hasProfile(CAMERA_ID, profile));
+ CamcorderProfile camcorderProfile = CamcorderProfile.get(CAMERA_ID, profile);
+ videoEncoder = camcorderProfile.videoCodec;
+ audioEncoder = camcorderProfile.audioCodec;
+ frameRate = camcorderProfile.videoFrameRate;
+ videoWidth = camcorderProfile.videoFrameWidth;
+ videoHeight = camcorderProfile.videoFrameHeight;
+ bitRate = camcorderProfile.videoBitRate;
+ } else {
+ videoEncoder = MediaRecorderStressTestRunner.mVideoEncoder;
+ audioEncoder = MediaRecorderStressTestRunner.mAudioEncoder;
+ frameRate = MediaRecorderStressTestRunner.mFrameRate;
+ videoWidth = MediaRecorderStressTestRunner.mVideoWidth;
+ videoHeight = MediaRecorderStressTestRunner.mVideoHeight;
+ bitRate = MediaRecorderStressTestRunner.mBitRate;
+ }
+ iterations = MediaRecorderStressTestRunner.mIterations;
+ recordDuration = MediaRecorderStressTestRunner.mDuration;
+ removeVideo = MediaRecorderStressTestRunner.mRemoveVideo;
+
+ SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+ mOutput.write("Total number of loops: " + iterations + "\n");
+
try {
- output.write("No of loop: ");
- for (int i = 0; i < iterations; i++){
- filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
- Log.v(TAG, filename);
+ mOutput.write("No of loop: ");
+ for (int i = 0; i < iterations; i++) {
+ String fileName = String.format("%s/temp%d%s",
+ Environment.getExternalStorageDirectory(), i, OUTPUT_FILE_EXT);
+ Log.v(TAG, fileName);
+
runOnLooper(new Runnable() {
@Override
public void run() {
mRecorder = new MediaRecorder();
}
});
+
Log.v(TAG, "iterations : " + iterations);
- Log.v(TAG, "video_encoder : " + video_encoder);
- Log.v(TAG, "audio_encoder : " + audio_encoder);
- Log.v(TAG, "frame_rate : " + frame_rate);
- Log.v(TAG, "video_width : " + video_width);
- Log.v(TAG, "video_height : " + video_height);
- Log.v(TAG, "bit rate : " + bit_rate);
- Log.v(TAG, "record_duration : " + record_duration);
+ Log.v(TAG, "video encoder : " + videoEncoder);
+ Log.v(TAG, "audio encoder : " + audioEncoder);
+ Log.v(TAG, "frame rate : " + frameRate);
+ Log.v(TAG, "video width : " + videoWidth);
+ Log.v(TAG, "video height : " + videoHeight);
+ Log.v(TAG, "bit rate : " + bitRate);
+ Log.v(TAG, "record duration : " + recordDuration);
mRecorder.setOnErrorListener(mRecorderErrorCallback);
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setOutputFile(filename);
- mRecorder.setVideoFrameRate(frame_rate);
- mRecorder.setVideoSize(video_width, video_height);
- mRecorder.setVideoEncoder(video_encoder);
- mRecorder.setAudioEncoder(audio_encoder);
- mRecorder.setVideoEncodingBitRate(bit_rate);
+ mRecorder.setOutputFile(fileName);
+ mRecorder.setVideoFrameRate(frameRate);
+ mRecorder.setVideoSize(videoWidth, videoHeight);
+ mRecorder.setVideoEncoder(videoEncoder);
+ mRecorder.setAudioEncoder(audioEncoder);
+ mRecorder.setVideoEncodingBitRate(bitRate);
+
Log.v(TAG, "mediaRecorder setPreview");
- mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+ mRecorder.setPreviewDisplay(surfaceHolder.getSurface());
mRecorder.prepare();
mRecorder.start();
- Thread.sleep(record_duration);
+ Thread.sleep(recordDuration);
Log.v(TAG, "Before stop");
mRecorder.stop();
mRecorder.release();
+
//start the playback
MediaPlayer mp = new MediaPlayer();
- mp.setDataSource(filename);
+ mp.setDataSource(fileName);
mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
mp.prepare();
mp.start();
- Thread.sleep(record_duration);
+ Thread.sleep(recordDuration);
mp.release();
- validateRecordedVideo(filename);
- if (remove_video) {
- removeRecordedVideo(filename);
+ validateRecordedVideo(fileName);
+ if (removeVideo) {
+ removeRecordedVideo(fileName);
}
- output.write(", " + i);
+ if (i == 0) {
+ mOutput.write(i + 1);
+ } else {
+ mOutput.write(String.format(", %d", (i + 1)));
+ }
}
} catch (Exception e) {
- Log.v(TAG, e.toString());
- assertTrue("record and playback", false);
+ Log.e(TAG, e.toString());
+ fail("Record and playback");
}
- output.write("\n\n");
- output.close();
+ }
+
+ // Record and playback stress test @ 1080P quality
+ @LargeTest
+ public void testStressRecordVideoAndPlayback1080P() throws Exception {
+ recordVideoAndPlayback(CamcorderProfile.QUALITY_1080P);
+ }
+
+ // Record and playback stress test @ 720P quality
+ @LargeTest
+ public void testStressRecordVideoAndPlayback720P() throws Exception {
+ recordVideoAndPlayback(CamcorderProfile.QUALITY_720P);
+ }
+
+ // Record and playback stress test @ 480P quality
+ @LargeTest
+ public void testStressRecordVideoAndPlayback480P() throws Exception {
+ recordVideoAndPlayback(CamcorderProfile.QUALITY_480P);
+ }
+
+ // This test method uses the codec info from the test runner. Use this
+ // for more granular control of video encoding.
+ @LargeTest
+ public void defaultStressRecordVideoAndPlayback() throws Exception {
+ recordVideoAndPlayback(USE_TEST_RUNNER_PROFILE);
}
// Test case for stressing time lapse
@@ -405,21 +458,19 @@
public void testStressTimeLapse() throws Exception {
SurfaceHolder mSurfaceHolder;
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
- int record_duration = MediaRecorderStressTestRunner.mTimeLapseDuration;
- boolean remove_video = MediaRecorderStressTestRunner.mRemoveVideo;
+ int recordDuration = MediaRecorderStressTestRunner.mTimeLapseDuration;
+ boolean removeVideo = MediaRecorderStressTestRunner.mRemoveVideo;
double captureRate = MediaRecorderStressTestRunner.mCaptureRate;
- String filename;
- File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
- output.write("Start camera time lapse stress:\n");
- output.write("Total number of loops: " + NUMBER_OF_TIME_LAPSE_LOOPS + "\n");
+ Log.v(TAG, "Start camera time lapse stress:");
+ mOutput.write("Total number of loops: " + NUMBER_OF_TIME_LAPSE_LOOPS + "\n");
try {
- for (int j = 0, n = Camera.getNumberOfCameras(); j < n; j++) {
- output.write("No of loop: camera " + j);
- for (int i = 0; i < NUMBER_OF_TIME_LAPSE_LOOPS; i++) {
- filename = OUTPUT_FILE + j + "_" + i + OUTPUT_FILE_EXT;
- Log.v(TAG, filename);
+ for (int i = 0, n = Camera.getNumberOfCameras(); i < n; i++) {
+ mOutput.write("No of loop: camera " + i);
+ for (int j = 0; j < NUMBER_OF_TIME_LAPSE_LOOPS; j++) {
+ String fileName = String.format("%s/temp%d_%d%s",
+ Environment.getExternalStorageDirectory(), i, j, OUTPUT_FILE_EXT);
+ Log.v(TAG, fileName);
runOnLooper(new Runnable() {
@Override
public void run() {
@@ -438,12 +489,12 @@
CamcorderProfile.get(j, CamcorderProfile.QUALITY_TIME_LAPSE_HIGH);
mRecorder.setProfile(profile);
- // Set the timelapse setting; 0.1 = 10 sec timelapse, 0.5 = 2 sec timelapse, etc.
+ // Set the timelapse setting; 0.1 = 10 sec timelapse, 0.5 = 2 sec timelapse, etc
// http://developer.android.com/guide/topics/media/camera.html#time-lapse-video
mRecorder.setCaptureRate(captureRate);
// Set output file
- mRecorder.setOutputFile(filename);
+ mRecorder.setOutputFile(fileName);
// Set the preview display
Log.v(TAG, "mediaRecorder setPreviewDisplay");
@@ -451,40 +502,40 @@
mRecorder.prepare();
mRecorder.start();
- Thread.sleep(record_duration);
+ Thread.sleep(recordDuration);
Log.v(TAG, "Before stop");
mRecorder.stop();
mRecorder.release();
// Start the playback
MediaPlayer mp = new MediaPlayer();
- mp.setDataSource(filename);
+ mp.setDataSource(fileName);
mp.setDisplay(mSurfaceHolder);
mp.prepare();
mp.start();
Thread.sleep(TIME_LAPSE_PLAYBACK_WAIT_TIME);
mp.release();
- validateRecordedVideo(filename);
- if (remove_video) {
- removeRecordedVideo(filename);
+ validateRecordedVideo(fileName);
+ if (removeVideo) {
+ removeRecordedVideo(fileName);
}
- output.write(", " + i);
+
+ if (j == 0) {
+ mOutput.write(j + 1);
+ } else {
+ mOutput.write(String.format(", %d", (j + 1)));
+ }
}
}
+ } catch (IllegalStateException e) {
+ Log.e(TAG, e.toString());
+ fail("Camera time lapse stress test IllegalStateException");
+ } catch (IOException e) {
+ Log.e(TAG, e.toString());
+ fail("Camera time lapse stress test IOException");
+ } catch (Exception e) {
+ Log.e(TAG, e.toString());
+ fail("Camera time lapse stress test Exception");
}
- catch (IllegalStateException e) {
- assertTrue("Camera time lapse stress test IllegalStateException", false);
- Log.v(TAG, e.toString());
- }
- catch (IOException e) {
- assertTrue("Camera time lapse stress test IOException", false);
- Log.v(TAG, e.toString());
- }
- catch (Exception e) {
- assertTrue("Camera time lapse stress test Exception", false);
- Log.v(TAG, e.toString());
- }
- output.write("\n\n");
- output.close();
}
}
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_ringer_silent.png
new file mode 100644
index 0000000..6872ec8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_ringer_vibrate.png
new file mode 100644
index 0000000..98520d3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_ringer_silent.png
new file mode 100644
index 0000000..66b4741
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_ringer_vibrate.png
new file mode 100644
index 0000000..f8abf25
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_ringer_silent.png
new file mode 100644
index 0000000..629b5f8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_ringer_vibrate.png
new file mode 100644
index 0000000..8e3e8b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index dbc55c8..39d56a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -118,12 +118,7 @@
mIcon = icon.clone();
setContentDescription(icon.contentDescription);
if (!iconEquals) {
- Drawable drawable = getIcon(icon);
- if (drawable == null) {
- Slog.w(TAG, "No icon for slot " + mSlot);
- return false;
- }
- setImageDrawable(drawable);
+ if (!updateDrawable(false /* no clear */)) return false;
}
if (!levelEquals) {
setImageLevel(icon.iconLevel);
@@ -149,6 +144,23 @@
return true;
}
+ public void updateDrawable() {
+ updateDrawable(true /* with clear */);
+ }
+
+ private boolean updateDrawable(boolean withClear) {
+ Drawable drawable = getIcon(mIcon);
+ if (drawable == null) {
+ Slog.w(TAG, "No icon for slot " + mSlot);
+ return false;
+ }
+ if (withClear) {
+ setImageDrawable(null);
+ }
+ setImageDrawable(drawable);
+ return true;
+ }
+
private Drawable getIcon(StatusBarIcon icon) {
return getIcon(getContext(), icon);
}
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 a5d782e..3227a34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -837,6 +837,16 @@
mWindowManager.addView(mIntruderAlertView, lp);
}
+ public void refreshAllStatusBarIcons() {
+ final int count = mStatusIcons.getChildCount();
+ for (int n = 0; n < count; n++) {
+ View child = mStatusIcons.getChildAt(n);
+ if (child instanceof StatusBarIconView) {
+ ((StatusBarIconView) child).updateDrawable();
+ }
+ }
+ }
+
public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
if (SPEW) Slog.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
+ " icon=" + icon);
@@ -984,6 +994,8 @@
mNotificationButton.setImageDrawable(null);
mNotificationButton.setImageResource(R.drawable.ic_notifications);
}
+
+ refreshAllStatusBarIcons();
}
private void updateShowSearchHoldoff() {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index dfc9044..71e80831d 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -412,6 +412,8 @@
boolean mForceStatusBar;
boolean mForceStatusBarFromKeyguard;
boolean mHideLockScreen;
+ boolean mForcingShowNavBar;
+ int mForcingShowNavBarLayer;
// States of keyguard dismiss.
private static final int DISMISS_KEYGUARD_NONE = 0; // Keyguard not being dismissed.
@@ -2952,6 +2954,8 @@
mTopFullscreenOpaqueWindowState = null;
mForceStatusBar = false;
mForceStatusBarFromKeyguard = false;
+ mForcingShowNavBar = false;
+ mForcingShowNavBarLayer = -1;
mHideLockScreen = false;
mAllowLockscreenWhenOn = false;
@@ -2966,6 +2970,13 @@
WindowManager.LayoutParams attrs) {
if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
+ win.isVisibleOrBehindKeyguardLw());
+ if (mTopFullscreenOpaqueWindowState == null && (win.getAttrs().privateFlags
+ &WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_NAV_BAR) != 0) {
+ if (mForcingShowNavBarLayer < 0) {
+ mForcingShowNavBar = true;
+ mForcingShowNavBarLayer = win.getSurfaceLayer();
+ }
+ }
if (mTopFullscreenOpaqueWindowState == null &&
win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
@@ -4494,9 +4505,13 @@
// will quickly lose focus once it correctly gets hidden.
return 0;
}
- final int visibility = mFocusedWindow.getSystemUiVisibility()
+ int tmpVisibility = mFocusedWindow.getSystemUiVisibility()
& ~mResettingSystemUiFlags
& ~mForceClearedSystemUiFlags;
+ if (mForcingShowNavBar && mFocusedWindow.getSurfaceLayer() < mForcingShowNavBarLayer) {
+ tmpVisibility &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
+ }
+ final int visibility = tmpVisibility;
int diff = visibility ^ mLastSystemUiFlags;
final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
if (diff == 0 && mLastFocusNeedsMenu == needsMenu
@@ -4692,6 +4707,11 @@
pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
pw.println(mTopFullscreenOpaqueWindowState);
}
+ if (mForcingShowNavBar) {
+ pw.print(prefix); pw.print("mForcingShowNavBar=");
+ pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
+ pw.println(mForcingShowNavBarLayer);
+ }
pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java
new file mode 100644
index 0000000..5ad4be8
--- /dev/null
+++ b/services/java/com/android/server/AppOpsService.java
@@ -0,0 +1,260 @@
+/*
+ * 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.server;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashMap;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Binder;
+import android.os.Environment;
+import android.os.Process;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TimeUtils;
+
+import com.android.internal.app.IAppOpsService;
+
+public class AppOpsService extends IAppOpsService.Stub {
+ static final String TAG = "AppOps";
+
+ Context mContext;
+ final AtomicFile mFile;
+
+ final SparseArray<HashMap<String, Ops>> mUidOps
+ = new SparseArray<HashMap<String, Ops>>();
+
+ final static class Ops extends SparseArray<Op> {
+ public final String packageName;
+
+ public Ops(String _packageName) {
+ packageName = _packageName;
+ }
+ }
+
+ final static class Op {
+ public final int op;
+ public int duration;
+ public long time;
+
+ public Op(int _op) {
+ op = _op;
+ }
+ }
+
+ public AppOpsService() {
+ mFile = new AtomicFile(new File(Environment.getSecureDataDirectory(), "appops.xml"));
+ }
+
+ public void publish(Context context) {
+ mContext = context;
+ ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
+ }
+
+ public void shutdown() {
+ Slog.w(TAG, "Writing app ops before shutdown...");
+ }
+
+ @Override
+ public int noteOperation(int code, int uid, String packageName) {
+ uid = handleIncomingUid(uid);
+ synchronized (this) {
+ Op op = getOpLocked(code, uid, packageName);
+ if (op == null) {
+ return AppOpsManager.MODE_IGNORED;
+ }
+ if (op.duration == -1) {
+ Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
+ + " code " + code + " time=" + op.time + " duration=" + op.duration);
+ }
+ op.time = System.currentTimeMillis();
+ op.duration = 0;
+ }
+ return AppOpsManager.MODE_ALLOWED;
+ }
+
+ @Override
+ public int startOperation(int code, int uid, String packageName) {
+ uid = handleIncomingUid(uid);
+ synchronized (this) {
+ Op op = getOpLocked(code, uid, packageName);
+ if (op == null) {
+ return AppOpsManager.MODE_IGNORED;
+ }
+ if (op.duration == -1) {
+ Slog.w(TAG, "Starting op not finished: uid " + uid + " pkg " + packageName
+ + " code " + code + " time=" + op.time + " duration=" + op.duration);
+ }
+ op.time = System.currentTimeMillis();
+ op.duration = -1;
+ }
+ return AppOpsManager.MODE_ALLOWED;
+ }
+
+ @Override
+ public void finishOperation(int code, int uid, String packageName) {
+ uid = handleIncomingUid(uid);
+ synchronized (this) {
+ Op op = getOpLocked(code, uid, packageName);
+ if (op == null) {
+ return;
+ }
+ if (op.duration != -1) {
+ Slog.w(TAG, "Ignoring finishing op not started: uid " + uid + " pkg " + packageName
+ + " code " + code + " time=" + op.time + " duration=" + op.duration);
+ return;
+ }
+ op.duration = (int)(System.currentTimeMillis() - op.time);
+ }
+ }
+
+ @Override
+ public int noteTimedOperation(int code, int uid, String packageName, int duration) {
+ uid = handleIncomingUid(uid);
+ synchronized (this) {
+ Op op = getOpLocked(code, uid, packageName);
+ if (op == null) {
+ return AppOpsManager.MODE_IGNORED;
+ }
+ if (op.duration == -1) {
+ Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
+ + " code " + code + " time=" + op.time + " duration=" + op.duration);
+ }
+ op.time = System.currentTimeMillis();
+ op.duration = duration;
+ }
+ return AppOpsManager.MODE_ALLOWED;
+ }
+
+ @Override
+ public void earlyFinishOperation(int code, int uid, String packageName) {
+ uid = handleIncomingUid(uid);
+ synchronized (this) {
+ Op op = getOpLocked(code, uid, packageName);
+ if (op == null) {
+ return;
+ }
+ if (op.duration != -1) {
+ Slog.w(TAG, "Noting timed op not finished: uid " + uid + " pkg " + packageName
+ + " code " + code + " time=" + op.time + " duration=" + op.duration);
+ }
+ int newDuration = (int)(System.currentTimeMillis() - op.time);
+ if (newDuration < op.duration) {
+ op.duration = newDuration;
+ }
+ }
+ }
+
+ private int handleIncomingUid(int uid) {
+ if (uid == Binder.getCallingUid()) {
+ return uid;
+ }
+ if (Binder.getCallingPid() == Process.myPid()) {
+ return uid;
+ }
+ mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+ Binder.getCallingPid(), Binder.getCallingUid(), null);
+ return uid;
+ }
+
+ private Op getOpLocked(int code, int uid, String packageName) {
+ HashMap<String, Ops> pkgOps = mUidOps.get(uid);
+ if (pkgOps == null) {
+ pkgOps = new HashMap<String, Ops>();
+ mUidOps.put(uid, pkgOps);
+ }
+ Ops ops = pkgOps.get(packageName);
+ if (ops == null) {
+ // This is the first time we have seen this package name under this uid,
+ // so let's make sure it is valid.
+ // XXX for now we always allow null through until we can fix everything
+ // to provide the name.
+ if (packageName != null) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ int pkgUid = -1;
+ try {
+ pkgUid = mContext.getPackageManager().getPackageUid(packageName,
+ UserHandle.getUserId(uid));
+ } catch (NameNotFoundException e) {
+ }
+ if (pkgUid != uid) {
+ // Oops! The package name is not valid for the uid they are calling
+ // under. Abort.
+ Slog.w(TAG, "Bad call: specified package " + packageName
+ + " under uid " + uid + " but it is really " + pkgUid);
+ return null;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ ops = new Ops(packageName);
+ pkgOps.put(packageName, ops);
+ }
+ Op op = ops.get(code);
+ if (op == null) {
+ op = new Op(code);
+ ops.put(code, op);
+ }
+ return op;
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump ApOps service from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ synchronized (this) {
+ pw.println("Current AppOps Service state:");
+ for (int i=0; i<mUidOps.size(); i++) {
+ pw.print(" Uid "); UserHandle.formatUid(pw, mUidOps.keyAt(i)); pw.println(":");
+ HashMap<String, Ops> pkgOps = mUidOps.valueAt(i);
+ for (Ops ops : pkgOps.values()) {
+ pw.print(" Package "); pw.print(ops.packageName); pw.println(":");
+ for (int j=0; j<ops.size(); j++) {
+ Op op = ops.valueAt(j);
+ pw.print(" "); pw.print(AppOpsManager.opToString(op.op));
+ pw.print(": time=");
+ TimeUtils.formatDuration(System.currentTimeMillis()-op.time, pw);
+ pw.print(" ago");
+ if (op.duration == -1) {
+ pw.println(" (running)");
+ } else {
+ pw.print("; duration=");
+ TimeUtils.formatDuration(op.duration, pw);
+ pw.println();
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 83b94e2..9e40dc5 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -53,6 +54,7 @@
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
@@ -60,6 +62,7 @@
import android.util.Log;
import android.util.Slog;
+import com.android.internal.app.IAppOpsService;
import com.android.internal.content.PackageMonitor;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
@@ -124,6 +127,7 @@
private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
private final Context mContext;
+ private final AppOpsManager mAppOps;
// used internally for synchronization
private final Object mLock = new Object();
@@ -187,6 +191,7 @@
public LocationManagerService(Context context) {
super();
mContext = context;
+ mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
if (D) Log.d(TAG, "Constructed");
@@ -524,6 +529,10 @@
}
public boolean callLocationChangedLocked(Location location) {
+ if (mAppOps.noteOpNoThrow(AppOpsManager.OP_LOCATION, mUid, mPackageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ return true;
+ }
if (mListener != null) {
try {
synchronized (this) {
@@ -1162,7 +1171,7 @@
private Receiver checkListenerOrIntent(ILocationListener listener, PendingIntent intent,
int pid, int uid, String packageName) {
if (intent == null && listener == null) {
- throw new IllegalArgumentException("need eiter listener or intent");
+ throw new IllegalArgumentException("need either listener or intent");
} else if (intent != null && listener != null) {
throw new IllegalArgumentException("cannot register both listener and intent");
} else if (intent != null) {
@@ -1185,11 +1194,14 @@
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
- Receiver recevier = checkListenerOrIntent(listener, intent, pid, uid, packageName);
-
// providers may use public location API's, need to clear identity
long identity = Binder.clearCallingIdentity();
try {
+ // We don't check for MODE_IGNORED here; we will do that when we go to deliver
+ // a location.
+ mAppOps.noteOp(AppOpsManager.OP_LOCATION, uid, packageName);
+ Receiver recevier = checkListenerOrIntent(listener, intent, pid, uid, packageName);
+
synchronized (mLock) {
requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
}
@@ -1296,8 +1308,14 @@
request.getProvider());
// no need to sanitize this request, as only the provider name is used
- long identity = Binder.clearCallingIdentity();
+ final int uid = Binder.getCallingUid();
+ final long identity = Binder.clearCallingIdentity();
try {
+ if (mAppOps.noteOp(AppOpsManager.OP_LOCATION, uid, packageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ return null;
+ }
+
if (mBlacklist.isBlacklisted(packageName)) {
if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
packageName);
@@ -1381,13 +1399,24 @@
@Override
- public boolean addGpsStatusListener(IGpsStatusListener listener) {
+ public boolean addGpsStatusListener(IGpsStatusListener listener, String packageName) {
if (mGpsStatusProvider == null) {
return false;
}
checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
LocationManager.GPS_PROVIDER);
+ final int uid = Binder.getCallingUid();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (mAppOps.noteOp(AppOpsManager.OP_LOCATION, uid, packageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ return false;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+
try {
mGpsStatusProvider.addGpsStatusListener(listener);
} catch (RemoteException e) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a7b502a..c33eb2b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -261,7 +261,6 @@
ServiceManager.addService(Context.USER_SERVICE,
UserManagerService.getInstance());
-
mContentResolver = context.getContentResolver();
// The AccountManager must come before the ContentService
diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java
index df91dec..69379f1 100644
--- a/services/java/com/android/server/VibratorService.java
+++ b/services/java/com/android/server/VibratorService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -30,6 +31,7 @@
import android.os.RemoteException;
import android.os.IBinder;
import android.os.Binder;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.Vibrator;
@@ -39,6 +41,9 @@
import android.util.Slog;
import android.view.InputDevice;
+import com.android.internal.app.IAppOpsService;
+import com.android.internal.app.IBatteryStats;
+
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.ListIterator;
@@ -54,6 +59,8 @@
private final Context mContext;
private final PowerManager.WakeLock mWakeLock;
+ private final IAppOpsService mAppOpsService;
+ private final IBatteryStats mBatteryStatsService;
private InputManager mIm;
volatile VibrateThread mThread;
@@ -64,6 +71,8 @@
private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators
private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators
+ private int mCurVibUid = -1;
+
native static boolean vibratorExists();
native static void vibratorOn(long milliseconds);
native static void vibratorOff();
@@ -75,23 +84,25 @@
private final long[] mPattern;
private final int mRepeat;
private final int mUid;
+ private final String mPackageName;
- Vibration(IBinder token, long millis, int uid) {
- this(token, millis, null, 0, uid);
+ Vibration(IBinder token, long millis, int uid, String packageName) {
+ this(token, millis, null, 0, uid, packageName);
}
- Vibration(IBinder token, long[] pattern, int repeat, int uid) {
- this(token, 0, pattern, repeat, uid);
+ Vibration(IBinder token, long[] pattern, int repeat, int uid, String packageName) {
+ this(token, 0, pattern, repeat, uid, packageName);
}
private Vibration(IBinder token, long millis, long[] pattern,
- int repeat, int uid) {
+ int repeat, int uid, String packageName) {
mToken = token;
mTimeout = millis;
mStartTime = SystemClock.uptimeMillis();
mPattern = pattern;
mRepeat = repeat;
mUid = uid;
+ mPackageName = packageName;
}
public void binderDied() {
@@ -131,6 +142,9 @@
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
mWakeLock.setReferenceCounted(true);
+ mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE));
+ mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
+
mVibrations = new LinkedList<Vibration>();
IntentFilter filter = new IntentFilter();
@@ -164,7 +178,7 @@
return doVibratorExists();
}
- public void vibrate(long milliseconds, IBinder token) {
+ public void vibrate(String packageName, long milliseconds, IBinder token) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires VIBRATE permission");
@@ -180,12 +194,18 @@
return;
}
- Vibration vib = new Vibration(token, milliseconds, uid);
- synchronized (mVibrations) {
- removeVibrationLocked(token);
- doCancelVibrateLocked();
- mCurrentVibration = vib;
- startVibrationLocked(vib);
+ Vibration vib = new Vibration(token, milliseconds, uid, packageName);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mVibrations) {
+ removeVibrationLocked(token);
+ doCancelVibrateLocked();
+ mCurrentVibration = vib;
+ startVibrationLocked(vib);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
@@ -199,7 +219,7 @@
return true;
}
- public void vibratePattern(long[] pattern, int repeat, IBinder token) {
+ public void vibratePattern(String packageName, long[] pattern, int repeat, IBinder token) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires VIBRATE permission");
@@ -224,7 +244,7 @@
return;
}
- Vibration vib = new Vibration(token, pattern, repeat, uid);
+ Vibration vib = new Vibration(token, pattern, repeat, uid, packageName);
try {
token.linkToDeath(vib, 0);
} catch (RemoteException e) {
@@ -291,11 +311,13 @@
}
doVibratorOff();
mH.removeCallbacks(mVibrationRunnable);
+ reportFinishVibrationLocked();
}
// Lock held on mVibrations
private void startNextVibrationLocked() {
if (mVibrations.size() <= 0) {
+ reportFinishVibrationLocked();
mCurrentVibration = null;
return;
}
@@ -305,8 +327,19 @@
// Lock held on mVibrations
private void startVibrationLocked(final Vibration vib) {
+ try {
+ int mode = mAppOpsService.startOperation(AppOpsManager.OP_VIBRATE, vib.mUid, vib.mPackageName);
+ if (mode != AppOpsManager.MODE_ALLOWED) {
+ if (mode == AppOpsManager.MODE_ERRORED) {
+ Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid);
+ }
+ mH.post(mVibrationRunnable);
+ return;
+ }
+ } catch (RemoteException e) {
+ }
if (vib.mTimeout != 0) {
- doVibratorOn(vib.mTimeout);
+ doVibratorOn(vib.mTimeout, vib.mUid);
mH.postDelayed(mVibrationRunnable, vib.mTimeout);
} else {
// mThread better be null here. doCancelVibrate should always be
@@ -316,6 +349,17 @@
}
}
+ private void reportFinishVibrationLocked() {
+ if (mCurrentVibration != null) {
+ try {
+ mAppOpsService.finishOperation(AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid,
+ mCurrentVibration.mPackageName);
+ } catch (RemoteException e) {
+ }
+ mCurrentVibration = null;
+ }
+ }
+
// Lock held on mVibrations
private Vibration removeVibrationLocked(IBinder token) {
ListIterator<Vibration> iter = mVibrations.listIterator(0);
@@ -413,8 +457,13 @@
return vibratorExists();
}
- private void doVibratorOn(long millis) {
+ private void doVibratorOn(long millis, int uid) {
synchronized (mInputDeviceVibrators) {
+ try {
+ mBatteryStatsService.noteVibratorOn(uid, millis);
+ mCurVibUid = uid;
+ } catch (RemoteException e) {
+ }
final int vibratorCount = mInputDeviceVibrators.size();
if (vibratorCount != 0) {
for (int i = 0; i < vibratorCount; i++) {
@@ -428,6 +477,13 @@
private void doVibratorOff() {
synchronized (mInputDeviceVibrators) {
+ if (mCurVibUid >= 0) {
+ try {
+ mBatteryStatsService.noteVibratorOff(mCurVibUid);
+ } catch (RemoteException e) {
+ }
+ mCurVibUid = -1;
+ }
final int vibratorCount = mInputDeviceVibrators.size();
if (vibratorCount != 0) {
for (int i = 0; i < vibratorCount; i++) {
@@ -470,10 +526,11 @@
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
synchronized (this) {
+ final long[] pattern = mVibration.mPattern;
+ final int len = pattern.length;
+ final int repeat = mVibration.mRepeat;
+ final int uid = mVibration.mUid;
int index = 0;
- long[] pattern = mVibration.mPattern;
- int len = pattern.length;
- int repeat = mVibration.mRepeat;
long duration = 0;
while (!mDone) {
@@ -493,7 +550,7 @@
// duration is saved for delay() at top of loop
duration = pattern[index++];
if (duration > 0) {
- VibratorService.this.doVibratorOn(duration);
+ VibratorService.this.doVibratorOn(duration, uid);
}
} else {
if (repeat < 0) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 62af91e..b08fc28 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -21,6 +21,7 @@
import com.android.internal.R;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.ProcessStats;
+import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
import com.android.server.IntentResolver;
import com.android.server.ProcessMap;
@@ -619,9 +620,14 @@
final BatteryStatsService mBatteryStatsService;
/**
- * information about component usage
+ * Information about component usage
*/
final UsageStatsService mUsageStatsService;
+
+ /**
+ * Information about and control over application operations
+ */
+ final AppOpsService mAppOpsService;
/**
* Current configuration information. HistoryRecord objects are given
@@ -1450,7 +1456,8 @@
m.mBatteryStatsService.publish(context);
m.mUsageStatsService.publish(context);
-
+ m.mAppOpsService.publish(context);
+
synchronized (thr) {
thr.mReady = true;
thr.notifyAll();
@@ -1613,9 +1620,10 @@
mOnBattery = DEBUG_POWER ? true
: mBatteryStatsService.getActiveStatistics().getIsOnBattery();
mBatteryStatsService.getActiveStatistics().setCallback(this);
-
+
mUsageStatsService = new UsageStatsService(new File(
systemDir, "usagestats").toString());
+ mAppOpsService = new AppOpsService();
mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
// User 0 is the first and only user that runs at boot.
@@ -7174,7 +7182,8 @@
}
}
}
-
+
+ mAppOpsService.shutdown();
mUsageStatsService.shutdown();
mBatteryStatsService.shutdown();
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index ab20208..d19c7f6 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -144,6 +144,20 @@
}
}
+ public void noteVibratorOn(int uid, long durationMillis) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteVibratorOnLocked(uid, durationMillis);
+ }
+ }
+
+ public void noteVibratorOff(int uid) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteVibratorOffLocked(uid);
+ }
+ }
+
public void noteStartGps(int uid) {
enforceCallingPermission();
synchronized (mStats) {
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 7f059f5..f1739d5 100644
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -17,6 +17,7 @@
package com.android.server.location;
import android.app.AlarmManager;
+import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -56,6 +57,8 @@
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;
import android.util.NtpTrustedTime;
+
+import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.internal.location.GpsNetInitiatedHandler;
import com.android.internal.location.ProviderProperties;
@@ -305,6 +308,7 @@
private final PendingIntent mWakeupIntent;
private final PendingIntent mTimeoutIntent;
+ private final IAppOpsService mAppOpsService;
private final IBatteryStats mBatteryStats;
// only modified on handler thread
@@ -434,6 +438,10 @@
mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ // App ops service to keep track of who is accessing the GPS
+ mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(
+ Context.APP_OPS_SERVICE));
+
// Battery statistics service to be notified when GPS turns on or off
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
@@ -863,6 +871,7 @@
}
if (newUid) {
try {
+ mAppOpsService.startOperation(AppOpsManager.OP_GPS, uid1, null);
mBatteryStats.noteStartGps(uid1);
} catch (RemoteException e) {
Log.w(TAG, "RemoteException", e);
@@ -882,6 +891,7 @@
if (oldUid) {
try {
mBatteryStats.noteStopGps(uid1);
+ mAppOpsService.finishOperation(AppOpsManager.OP_GPS, uid1, null);
} catch (RemoteException e) {
Log.w(TAG, "RemoteException", e);
}
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index e96820f..02a2c1b 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -188,12 +188,7 @@
}
}
- /**
- * @param restrictHomeDir if {@code true}, installd will create the application's
- * home directory with {@code 0700} permissions. If false, {@code 0751} will
- * be used instead.
- */
- public int install(String name, int uid, int gid, boolean restrictHomeDir) {
+ public int install(String name, int uid, int gid) {
StringBuilder builder = new StringBuilder("install");
builder.append(' ');
builder.append(name);
@@ -201,8 +196,6 @@
builder.append(uid);
builder.append(' ');
builder.append(gid);
- builder.append(' ');
- builder.append(restrictHomeDir);
return execute(builder.toString());
}
@@ -270,12 +263,7 @@
return execute(builder.toString());
}
- /**
- * @param restrictHomeDir if {@code true}, installd will create the application's
- * home directory with {@code 0700} permissions. If false, {@code 0751} will
- * be used instead.
- */
- public int createUserData(String name, int uid, int userId, boolean restrictHomeDir) {
+ public int createUserData(String name, int uid, int userId) {
StringBuilder builder = new StringBuilder("mkuserdata");
builder.append(' ');
builder.append(name);
@@ -283,8 +271,6 @@
builder.append(uid);
builder.append(' ');
builder.append(userId);
- builder.append(' ');
- builder.append(restrictHomeDir);
return execute(builder.toString());
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index aa2b461..2238f17 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -24,6 +24,7 @@
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static com.android.internal.util.ArrayUtils.appendInt;
import static com.android.internal.util.ArrayUtils.removeInt;
+import static libcore.io.OsConstants.S_ISLNK;
import static libcore.io.OsConstants.S_IRWXU;
import static libcore.io.OsConstants.S_IRGRP;
import static libcore.io.OsConstants.S_IXGRP;
@@ -110,6 +111,7 @@
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.Environment.UserEnvironment;
+import android.provider.Settings.Secure;
import android.security.SystemKeyStore;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -146,11 +148,13 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import libcore.io.ErrnoException;
import libcore.io.IoUtils;
import libcore.io.Libcore;
+import libcore.io.OsConstants;
import libcore.io.StructStat;
/**
@@ -3578,17 +3582,16 @@
}
}
- private int createDataDirsLI(String packageName, int uid, int targetSdkVersion) {
+ private int createDataDirsLI(String packageName, int uid) {
int[] users = sUserManager.getUserIds();
- boolean restrictHomeDir = (targetSdkVersion >= Build.VERSION_CODES.K);
- int res = mInstaller.install(packageName, uid, uid, restrictHomeDir);
+ int res = mInstaller.install(packageName, uid, uid);
if (res < 0) {
return res;
}
for (int user : users) {
if (user != 0) {
res = mInstaller.createUserData(packageName,
- UserHandle.getUid(user, uid), user, restrictHomeDir);
+ UserHandle.getUid(user, uid), user);
if (res < 0) {
return res;
}
@@ -3982,8 +3985,7 @@
recovered = true;
// And now re-install the app.
- ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
- pkg.applicationInfo.targetSdkVersion);
+ ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
if (ret == -1) {
// Ack should not happen!
msg = prefix + pkg.packageName
@@ -4028,9 +4030,8 @@
if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
Log.v(TAG, "Want this data dir: " + dataPath);
}
- // invoke installer to do the actual installation
- int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
- pkg.applicationInfo.targetSdkVersion);
+ //invoke installer to do the actual installation
+ int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
if (ret < 0) {
// Error from installer
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index f791a6e..06f11bc 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -25,6 +25,7 @@
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.XmlUtils;
+import com.android.server.IntentResolver;
import com.android.server.pm.PackageManagerService.DumpState;
import org.xmlpull.v1.XmlPullParser;
@@ -45,7 +46,6 @@
import android.content.pm.PackageUserState;
import android.content.pm.VerifierDeviceIdentity;
import android.os.Binder;
-import android.os.Build;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Process;
@@ -2335,11 +2335,9 @@
for (PackageSetting ps : mPackages.values()) {
// Only system apps are initially installed.
ps.setInstalled((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0, userHandle);
- boolean restrictHomeDir = (ps.pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.K);
// Need to create a data directory for all apps under this user.
installer.createUserData(ps.name,
- UserHandle.getUid(userHandle, ps.appId), userHandle,
- restrictHomeDir);
+ UserHandle.getUid(userHandle, ps.appId), userHandle);
}
readDefaultPreferredAppsLPw(userHandle);
writePackageRestrictionsLPr(userHandle);
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 2eba4e1..5ee52de 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -81,6 +81,13 @@
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public int getPackageUid(String packageName, int userHandle)
+ throws NameNotFoundException {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public PermissionInfo getPermissionInfo(String name, int flags)
throws NameNotFoundException {
diff --git a/tests/HwAccelerationTest/res/drawable/patch.9.png b/tests/HwAccelerationTest/res/drawable/patch.9.png
deleted file mode 100644
index e3b3639..0000000
--- a/tests/HwAccelerationTest/res/drawable/patch.9.png
+++ /dev/null
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colorcube.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colorcube.rs
index 5250474..fda0d1e 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colorcube.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colorcube.rs
@@ -62,10 +62,10 @@
uint4 yz01 = ((v001 * weight1.x) + (v101 * weight2.x)) >> (int4)8;
uint4 yz11 = ((v011 * weight1.x) + (v111 * weight2.x)) >> (int4)8;
- uint4 z0 = (yz00 * weight1.y) + (yz10 * weight2.y) >> (int4)16;
- uint4 z1 = (yz01 * weight1.y) + (yz11 * weight2.y) >> (int4)16;
+ uint4 z0 = ((yz00 * weight1.y) + (yz10 * weight2.y)) >> (int4)16;
+ uint4 z1 = ((yz01 * weight1.y) + (yz11 * weight2.y)) >> (int4)16;
- uint4 v = (z0 * weight1.z) + (z1 * weight2.z) >> (int4)16;
+ uint4 v = ((z0 * weight1.z) + (z1 * weight2.z)) >> (int4)16;
uint4 v2 = (v + 0x7f) >> (int4)8;
*out = convert_uchar4(v2);
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
index 227518f..19bea43 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
@@ -229,7 +229,7 @@
break;
}
- mTest.createBaseTest(this, mBitmapIn, mBitmapIn2);
+ mTest.createBaseTest(this, mBitmapIn, mBitmapIn2, mBitmapOut);
setupBars();
mTest.runTest();
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
index 9df2eff..dbbc594 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
@@ -88,18 +88,14 @@
return false;
}
- public final void createBaseTest(ImageProcessingActivity2 ipact, Bitmap b, Bitmap b2) {
+ public final void createBaseTest(ImageProcessingActivity2 ipact, Bitmap b, Bitmap b2, Bitmap outb) {
act = ipact;
mRS = RenderScript.create(act);
- mInPixelsAllocation = Allocation.createFromBitmap(mRS, b,
- Allocation.MipmapControl.MIPMAP_NONE,
- Allocation.USAGE_SCRIPT);
- mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, b2,
- Allocation.MipmapControl.MIPMAP_NONE,
- Allocation.USAGE_SCRIPT);
- mOutPixelsAllocation = Allocation.createFromBitmap(mRS, b,
- Allocation.MipmapControl.MIPMAP_NONE,
- Allocation.USAGE_SCRIPT);
+
+ mInPixelsAllocation = Allocation.createFromBitmap(mRS, b);
+ mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, b2);
+ mOutPixelsAllocation = Allocation.createFromBitmap(mRS, outb);
+
createTest(act.getResources());
}
diff --git a/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java b/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java
index 274ac00..2416828 100644
--- a/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java
+++ b/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java
@@ -46,7 +46,7 @@
*/
public void testVibrate() throws RemoteException {
try {
- mVibratorService.vibrate(2000, new Binder());
+ mVibratorService.vibrate(null, 2000, new Binder());
fail("vibrate did not throw SecurityException as expected");
} catch (SecurityException e) {
// expected
@@ -62,7 +62,7 @@
*/
public void testVibratePattern() throws RemoteException {
try {
- mVibratorService.vibratePattern(new long[] {0}, 0, new Binder());
+ mVibratorService.vibratePattern(null, new long[] {0}, 0, new Binder());
fail("vibratePattern did not throw SecurityException as expected");
} catch (SecurityException e) {
// expected