Merge changes I8de95add,Ia6f4ccfd into nyc-dev
* changes:
Remove unused event tags of IpConnectivityEvent
Better ConnectivityMetricsEvent printing
diff --git a/Android.mk b/Android.mk
index 1cde699..7d7aa48 100644
--- a/Android.mk
+++ b/Android.mk
@@ -598,6 +598,7 @@
frameworks/base/core/java/android/net/Uri.aidl \
frameworks/base/core/java/android/net/NetworkRequest.aidl \
frameworks/base/core/java/android/net/LinkAddress.aidl \
+ frameworks/base/core/java/android/util/MemoryIntArray.aidl \
frameworks/base/core/java/android/view/Display.aidl \
frameworks/base/core/java/android/view/InputDevice.aidl \
frameworks/base/core/java/android/view/InputEvent.aidl \
diff --git a/api/current.txt b/api/current.txt
index 9834c8c..f267789 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -513,6 +513,7 @@
field public static final int elevation = 16843840; // 0x1010440
field public static final int ellipsize = 16842923; // 0x10100ab
field public static final int ems = 16843096; // 0x1010158
+ field public static final int enableVrMode = 16844072; // 0x1010528
field public static final int enabled = 16842766; // 0x101000e
field public static final int end = 16843996; // 0x10104dc
field public static final int endColor = 16843166; // 0x101019e
@@ -32491,7 +32492,6 @@
field public static final java.lang.String RADIO_WIFI = "wifi";
field public static final java.lang.String SHOW_PROCESSES = "show_processes";
field public static final java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
- field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_global_version";
field public static final java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
field public static final java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
@@ -32551,7 +32551,6 @@
field public static final deprecated java.lang.String DEVICE_PROVISIONED = "device_provisioned";
field public static final java.lang.String ENABLED_ACCESSIBILITY_SERVICES = "enabled_accessibility_services";
field public static final java.lang.String ENABLED_INPUT_METHODS = "enabled_input_methods";
- field public static final java.lang.String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages";
field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
@@ -32572,7 +32571,6 @@
field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype";
field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname";
field public static final java.lang.String SKIP_FIRST_USE_HINTS = "skip_first_use_hints";
- field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
field public static final java.lang.String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
field public static final deprecated java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country";
field public static final deprecated java.lang.String TTS_DEFAULT_LANG = "tts_default_lang";
@@ -32687,7 +32685,6 @@
field public static final deprecated java.lang.String SHOW_WEB_SUGGESTIONS = "show_web_suggestions";
field public static final java.lang.String SOUND_EFFECTS_ENABLED = "sound_effects_enabled";
field public static final deprecated java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
- field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_system_version";
field public static final java.lang.String TEXT_AUTO_CAPS = "auto_caps";
field public static final java.lang.String TEXT_AUTO_PUNCTUATE = "auto_punctuate";
field public static final java.lang.String TEXT_AUTO_REPLACE = "auto_replace";
diff --git a/api/system-current.txt b/api/system-current.txt
index 11ae630..f9d8d34 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -617,6 +617,7 @@
field public static final int elevation = 16843840; // 0x1010440
field public static final int ellipsize = 16842923; // 0x10100ab
field public static final int ems = 16843096; // 0x1010158
+ field public static final int enableVrMode = 16844072; // 0x1010528
field public static final int enabled = 16842766; // 0x101000e
field public static final int end = 16843996; // 0x10104dc
field public static final int endColor = 16843166; // 0x101019e
@@ -35188,7 +35189,6 @@
field public static final java.lang.String RADIO_WIFI = "wifi";
field public static final java.lang.String SHOW_PROCESSES = "show_processes";
field public static final java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
- field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_global_version";
field public static final java.lang.String THEATER_MODE_ON = "theater_mode_on";
field public static final java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
@@ -35250,7 +35250,6 @@
field public static final deprecated java.lang.String DEVICE_PROVISIONED = "device_provisioned";
field public static final java.lang.String ENABLED_ACCESSIBILITY_SERVICES = "enabled_accessibility_services";
field public static final java.lang.String ENABLED_INPUT_METHODS = "enabled_input_methods";
- field public static final java.lang.String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages";
field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
@@ -35271,7 +35270,6 @@
field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype";
field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname";
field public static final java.lang.String SKIP_FIRST_USE_HINTS = "skip_first_use_hints";
- field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
field public static final java.lang.String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
field public static final deprecated java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country";
field public static final deprecated java.lang.String TTS_DEFAULT_LANG = "tts_default_lang";
@@ -35386,7 +35384,6 @@
field public static final deprecated java.lang.String SHOW_WEB_SUGGESTIONS = "show_web_suggestions";
field public static final java.lang.String SOUND_EFFECTS_ENABLED = "sound_effects_enabled";
field public static final deprecated java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
- field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_system_version";
field public static final java.lang.String TEXT_AUTO_CAPS = "auto_caps";
field public static final java.lang.String TEXT_AUTO_PUNCTUATE = "auto_punctuate";
field public static final java.lang.String TEXT_AUTO_REPLACE = "auto_replace";
diff --git a/api/test-current.txt b/api/test-current.txt
index 5dc6d51..25e58e2 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -513,6 +513,7 @@
field public static final int elevation = 16843840; // 0x1010440
field public static final int ellipsize = 16842923; // 0x10100ab
field public static final int ems = 16843096; // 0x1010158
+ field public static final int enableVrMode = 16844072; // 0x1010528
field public static final int enabled = 16842766; // 0x101000e
field public static final int end = 16843996; // 0x10104dc
field public static final int endColor = 16843166; // 0x101019e
@@ -32563,7 +32564,6 @@
field public static final java.lang.String RADIO_WIFI = "wifi";
field public static final java.lang.String SHOW_PROCESSES = "show_processes";
field public static final java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
- field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_global_version";
field public static final java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
field public static final java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
@@ -32644,7 +32644,6 @@
field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype";
field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname";
field public static final java.lang.String SKIP_FIRST_USE_HINTS = "skip_first_use_hints";
- field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
field public static final java.lang.String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
field public static final deprecated java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country";
field public static final deprecated java.lang.String TTS_DEFAULT_LANG = "tts_default_lang";
@@ -32760,7 +32759,6 @@
field public static final deprecated java.lang.String SHOW_WEB_SUGGESTIONS = "show_web_suggestions";
field public static final java.lang.String SOUND_EFFECTS_ENABLED = "sound_effects_enabled";
field public static final deprecated java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
- field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_system_version";
field public static final java.lang.String TEXT_AUTO_CAPS = "auto_caps";
field public static final java.lang.String TEXT_AUTO_PUNCTUATE = "auto_punctuate";
field public static final java.lang.String TEXT_AUTO_REPLACE = "auto_replace";
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index d44a1df..19cb927 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -464,6 +464,9 @@
case "-g":
sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
break;
+ case "--dont-kill":
+ sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
+ break;
case "--originating-uri":
sessionParams.originatingUri = Uri.parse(nextOptionData());
break;
@@ -499,6 +502,9 @@
sessionParams.volumeUuid = null;
}
break;
+ case "--force-sdk":
+ sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK;
+ break;
default:
throw new IllegalArgumentException("Unknown option " + opt);
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1da21b0..0764ff4 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3474,6 +3474,12 @@
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
+ // Normally the ViewRoot sets up callbacks with the Activity
+ // in addView->ViewRootImpl#setView. If we are instead reusing
+ // the decor view we have to notify the view root that the
+ // callbacks may have changed.
+ ViewRootImpl impl = decor.getViewRootImpl();
+ impl.notifyChildRebuilt();
}
if (a.mVisibleFromClient && !a.mWindowAdded) {
a.mWindowAdded = true;
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 0f4cbbb..167befc 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -191,6 +191,13 @@
public int resizeMode;
/**
+ * Name of the VrListenerService component to run for this activity.
+ * @see android.R.attr#enableVrMode
+ * @hide
+ */
+ public String requestedVrComponent;
+
+ /**
* Bit in {@link #flags} indicating whether this activity is able to
* run in multiple processes. If
* true, the system may instantiate it in the some process as the
@@ -794,6 +801,7 @@
lockTaskLaunchMode = orig.lockTaskLaunchMode;
windowLayout = orig.windowLayout;
resizeMode = orig.resizeMode;
+ requestedVrComponent = orig.requestedVrComponent;
}
/**
@@ -896,6 +904,9 @@
+ windowLayout.heightFraction + ", " + windowLayout.gravity);
}
pw.println(prefix + "resizeMode=" + resizeModeToString(resizeMode));
+ if (requestedVrComponent != null) {
+ pw.println(prefix + "requestedVrComponent=" + requestedVrComponent);
+ }
super.dumpBack(pw, prefix, flags);
}
@@ -939,6 +950,7 @@
dest.writeInt(0);
}
dest.writeInt(resizeMode);
+ dest.writeString(requestedVrComponent);
}
public static final Parcelable.Creator<ActivityInfo> CREATOR
@@ -972,6 +984,7 @@
windowLayout = new WindowLayout(source);
}
resizeMode = source.readInt();
+ requestedVrComponent = source.readString();
}
/**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b04cbc5..a96da09 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -684,6 +684,14 @@
public static final int INSTALL_DONT_KILL_APP = 0x00001000;
/**
+ * Flag parameter for {@link #installPackage} to indicate that this package is an
+ * upgrade to a package that refers to the SDK via release letter.
+ *
+ * @hide
+ */
+ public static final int INSTALL_FORCE_SDK = 0x00002000;
+
+ /**
* Flag parameter for
* {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate
* that you don't want to kill the app containing the component. Be careful when you set this
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 54091db..66c5000 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -652,6 +652,7 @@
public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
public final static int PARSE_ENFORCE_CODE = 1<<10;
public final static int PARSE_IS_EPHEMERAL = 1<<11;
+ public final static int PARSE_FORCE_SDK = 1<<12;
private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
@@ -3532,6 +3533,9 @@
a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
R.styleable.AndroidManifestActivity_directBootAware,
false);
+
+ a.info.requestedVrComponent =
+ sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
} else {
a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
a.info.configChanges = 0;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 9070ad9..faf5c64 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -81,13 +81,6 @@
public class ConnectivityManager {
private static final String TAG = "ConnectivityManager";
- private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
- new Class[]{ConnectivityManager.class}, new String[]{"CALLBACK_"});
-
- private static final String whatToString(int what) {
- return sMagicDecoderRing.get(what, Integer.toString(what));
- }
-
/**
* A change in network connectivity has occurred. A default connection has either
* been established or lost. The NetworkInfo for the affected network is
@@ -3360,4 +3353,32 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * A holder class for debug info (mapping CALLBACK values to field names). This is stored
+ * in a holder for two reasons:
+ * 1) The reflection necessary to establish the map can't be run at compile-time. Thus, this
+ * code will make the enclosing class not compile-time initializeable, deferring its
+ * initialization to zygote startup. This leads to dirty (but shared) memory.
+ * As this is debug info, use a holder that isn't initialized by default. This way the map
+ * will be created on demand, while ConnectivityManager can be compile-time initialized.
+ * 2) Static initialization is still preferred for its strong thread safety guarantees without
+ * requiring a lock.
+ */
+ private static class NoPreloadHolder {
+ public static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
+ new Class[]{ConnectivityManager.class}, new String[]{"CALLBACK_"});
+ }
+
+ static {
+ // When debug is enabled, aggressively initialize the holder by touching the field (which
+ // will guarantee static initialization).
+ if (CallbackHandler.DBG) {
+ Object dummy = NoPreloadHolder.sMagicDecoderRing;
+ }
+ }
+
+ private static final String whatToString(int what) {
+ return NoPreloadHolder.sMagicDecoderRing.get(what, Integer.toString(what));
+ }
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d80d4be..4ca1b97 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -16,6 +16,7 @@
package android.provider;
+import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -50,7 +51,6 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.Build.VERSION_CODES;
import android.speech.tts.TextToSpeech;
@@ -61,9 +61,12 @@
import android.util.LocaleList;
import android.util.Log;
+import android.util.MemoryIntArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.ILockSettings;
+import java.io.IOException;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
@@ -1282,6 +1285,29 @@
public static final String CALL_METHOD_GET_GLOBAL = "GET_global";
/**
+ * @hide - Specifies that the caller of the fast-path call()-based flow tracks
+ * the settings generation in order to cache values locally. If this key is
+ * mapped to a <code>null</code> string extra in the request bundle, the response
+ * bundle will contain the same key mapped to a parcelable extra which would be
+ * an {@link android.util.MemoryIntArray}. The response will also contain an
+ * integer mapped to the {@link #CALL_METHOD_GENERATION_INDEX_KEY} which is the
+ * index in the array clients should use to lookup the generation. For efficiency
+ * the caller should request the generation tracking memory array only if it
+ * doesn't already have it.
+ *
+ * @see #CALL_METHOD_GENERATION_INDEX_KEY
+ */
+ public static final String CALL_METHOD_TRACK_GENERATION_KEY = "_track_generation";
+
+ /**
+ * @hide Key with the location in the {@link android.util.MemoryIntArray} where
+ * to look up the generation id of the backing table.
+ *
+ * @see #CALL_METHOD_TRACK_GENERATION_KEY
+ */
+ public static final String CALL_METHOD_GENERATION_INDEX_KEY = "_generation_index";
+
+ /**
* @hide - User handle argument extra to the fast-path call()-based requests
*/
public static final String CALL_METHOD_USER_KEY = "_user";
@@ -1424,9 +1450,42 @@
}
}
+ private static final class GenerationTracker {
+ private final MemoryIntArray mArray;
+ private final int mIndex;
+ private int mCurrentGeneration;
+
+ public GenerationTracker(@NonNull MemoryIntArray array, int index) {
+ mArray = array;
+ mIndex = index;
+ mCurrentGeneration = readCurrentGeneration();
+ }
+
+ public boolean isGenerationChanged() {
+ final int currentGeneration = readCurrentGeneration();
+ if (currentGeneration >= 0) {
+ if (currentGeneration == mCurrentGeneration) {
+ return false;
+ }
+ mCurrentGeneration = currentGeneration;
+ }
+ return true;
+ }
+
+ private int readCurrentGeneration() {
+ try {
+ return mArray.get(mIndex);
+ } catch (IOException e) {
+ Log.e(TAG, "Error getting current generation", e);
+ }
+ return -1;
+ }
+ }
+
// Thread-safe.
private static class NameValueCache {
- private final String mVersionSystemProperty;
+ private static final boolean DEBUG = false;
+
private final Uri mUri;
private static final String[] SELECT_VALUE =
@@ -1435,7 +1494,6 @@
// Must synchronize on 'this' to access mValues and mValuesVersion.
private final HashMap<String, String> mValues = new HashMap<String, String>();
- private long mValuesVersion = 0;
// Initially null; set lazily and held forever. Synchronized on 'this'.
private IContentProvider mContentProvider = null;
@@ -1445,9 +1503,10 @@
private final String mCallGetCommand;
private final String mCallSetCommand;
- public NameValueCache(String versionSystemProperty, Uri uri,
- String getCommand, String setCommand) {
- mVersionSystemProperty = versionSystemProperty;
+ @GuardedBy("this")
+ private GenerationTracker mGenerationTracker;
+
+ public NameValueCache(Uri uri, String getCommand, String setCommand) {
mUri = uri;
mCallGetCommand = getCommand;
mCallSetCommand = setCommand;
@@ -1482,22 +1541,18 @@
public String getStringForUser(ContentResolver cr, String name, final int userHandle) {
final boolean isSelf = (userHandle == UserHandle.myUserId());
if (isSelf) {
- long newValuesVersion = SystemProperties.getLong(mVersionSystemProperty, 0);
-
- // Our own user's settings data uses a client-side cache
synchronized (this) {
- if (mValuesVersion != newValuesVersion) {
- if (LOCAL_LOGV || false) {
- Log.v(TAG, "invalidate [" + mUri.getLastPathSegment() + "]: current "
- + newValuesVersion + " != cached " + mValuesVersion);
+ if (mGenerationTracker != null) {
+ if (mGenerationTracker.isGenerationChanged()) {
+ if (DEBUG) {
+ Log.i(TAG, "Generation changed for type:"
+ + mUri.getPath() + " in package:"
+ + cr.getPackageName() +" and user:" + userHandle);
+ }
+ mValues.clear();
+ } else if (mValues.containsKey(name)) {
+ return mValues.get(name);
}
-
- mValues.clear();
- mValuesVersion = newValuesVersion;
- }
-
- if (mValues.containsKey(name)) {
- return mValues.get(name); // Could be null, that's OK -- negative caching
}
}
} else {
@@ -1518,12 +1573,42 @@
args = new Bundle();
args.putInt(CALL_METHOD_USER_KEY, userHandle);
}
+ boolean needsGenerationTracker = false;
+ synchronized (this) {
+ if (isSelf && mGenerationTracker == null) {
+ needsGenerationTracker = true;
+ if (args == null) {
+ args = new Bundle();
+ }
+ args.putString(CALL_METHOD_TRACK_GENERATION_KEY, null);
+ if (DEBUG) {
+ Log.i(TAG, "Requested generation tracker for type: "+ mUri.getPath()
+ + " in package:" + cr.getPackageName() +" and user:"
+ + userHandle);
+ }
+ }
+ }
Bundle b = cp.call(cr.getPackageName(), mCallGetCommand, name, args);
if (b != null) {
- String value = b.getPairValue();
+ String value = b.getString(Settings.NameValueTable.VALUE);
// Don't update our cache for reads of other users' data
if (isSelf) {
synchronized (this) {
+ if (needsGenerationTracker) {
+ MemoryIntArray array = b.getParcelable(
+ CALL_METHOD_TRACK_GENERATION_KEY);
+ final int index = b.getInt(
+ CALL_METHOD_GENERATION_INDEX_KEY, -1);
+ if (array != null && index >= 0) {
+ if (DEBUG) {
+ Log.i(TAG, "Received generation tracker for type:"
+ + mUri.getPath() + " in package:"
+ + cr.getPackageName() + " and user:"
+ + userHandle + " with index:" + index);
+ }
+ mGenerationTracker = new GenerationTracker(array, index);
+ }
+ }
mValues.put(name, value);
}
} else {
@@ -1592,8 +1677,6 @@
* functions for accessing individual settings entries.
*/
public static final class System extends NameValueTable {
- public static final String SYS_PROP_SETTING_VERSION = "sys.settings_system_version";
-
private static final float DEFAULT_FONT_SCALE = 1.0f;
/** @hide */
@@ -1608,7 +1691,6 @@
Uri.parse("content://" + AUTHORITY + "/system");
private static final NameValueCache sNameValueCache = new NameValueCache(
- SYS_PROP_SETTING_VERSION,
CONTENT_URI,
CALL_METHOD_GET_SYSTEM,
CALL_METHOD_PUT_SYSTEM);
@@ -3913,8 +3995,6 @@
* APIs for those values, not modified directly by applications.
*/
public static final class Secure extends NameValueTable {
- public static final String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
-
/**
* The content:// style URL for this table
*/
@@ -3923,7 +4003,6 @@
// Populated lazily, guarded by class object:
private static final NameValueCache sNameValueCache = new NameValueCache(
- SYS_PROP_SETTING_VERSION,
CONTENT_URI,
CALL_METHOD_GET_SECURE,
CALL_METHOD_PUT_SECURE);
@@ -5867,7 +5946,10 @@
/**
* Names of the packages that the current user has explicitly allowed to
* manage notification policy configuration, separated by ':'.
+ *
+ * @hide
*/
+ @TestApi
public static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES =
"enabled_notification_policy_access_packages";
@@ -6357,8 +6439,6 @@
* explicitly modify through the system UI or specialized APIs for those values.
*/
public static final class Global extends NameValueTable {
- public static final String SYS_PROP_SETTING_VERSION = "sys.settings_global_version";
-
/**
* The content:// style URL for global secure settings items. Not public.
*/
@@ -8409,7 +8489,6 @@
// Populated lazily, guarded by class object:
private static NameValueCache sNameValueCache = new NameValueCache(
- SYS_PROP_SETTING_VERSION,
CONTENT_URI,
CALL_METHOD_GET_GLOBAL,
CALL_METHOD_PUT_GLOBAL);
diff --git a/core/java/android/util/MemoryIntArray.aidl b/core/java/android/util/MemoryIntArray.aidl
new file mode 100644
index 0000000..3b15535
--- /dev/null
+++ b/core/java/android/util/MemoryIntArray.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+parcelable MemoryIntArray;
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
new file mode 100644
index 0000000..c3bd963
--- /dev/null
+++ b/core/java/android/util/MemoryIntArray.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+import android.os.Process;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.UUID;
+
+/**
+ * This class is an array of integers that is backed by shared memory.
+ * It is useful for efficiently sharing state between processes. The
+ * write and read operations are guaranteed to not result in read/
+ * write memory tear, i.e. they are atomic. However, multiple read/
+ * write operations are <strong>not</strong> synchronized between
+ * each other.
+ * <p>
+ * The data structure is designed to have one owner process that can
+ * read/write. There may be multiple client processes that can only read or
+ * read/write depending how the data structure was configured when
+ * instantiated. The owner process is the process that created the array.
+ * The shared memory is pinned (not reclaimed by the system) until the
+ * owning process dies or the data structure is closed. This class
+ * is <strong>not</strong> thread safe. You should not interact with
+ * an instance of this class once it is closed.
+ * </p>
+ *
+ * @hide
+ */
+public final class MemoryIntArray implements Parcelable, Closeable {
+ private static final int MAX_SIZE = 1024;
+
+ private final int mOwnerPid;
+ private final boolean mClientWritable;
+ private final long mMemoryAddr;
+ private ParcelFileDescriptor mFd;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param size The size of the array in terms of integer slots. Cannot be
+ * more than {@link #getMaxSize()}.
+ * @param clientWritable Whether other processes can write to the array.
+ * @throws IOException If an error occurs while accessing the shared memory.
+ */
+ public MemoryIntArray(int size, boolean clientWritable) throws IOException {
+ if (size > MAX_SIZE) {
+ throw new IllegalArgumentException("Max size is " + MAX_SIZE);
+ }
+ mOwnerPid = Process.myPid();
+ mClientWritable = clientWritable;
+ final String name = UUID.randomUUID().toString();
+ mFd = ParcelFileDescriptor.fromFd(nativeCreate(name, size));
+ mMemoryAddr = nativeOpen(mFd.getFd(), true, clientWritable);
+ }
+
+ private MemoryIntArray(Parcel parcel) throws IOException {
+ mOwnerPid = parcel.readInt();
+ mClientWritable = (parcel.readInt() == 1);
+ mFd = parcel.readParcelable(null);
+ if (mFd == null) {
+ throw new IOException("No backing file descriptor");
+ }
+ final long memoryAddress = parcel.readLong();
+ if (isOwner()) {
+ mMemoryAddr = memoryAddress;
+ } else {
+ mMemoryAddr = nativeOpen(mFd.getFd(), false, mClientWritable);
+ }
+ }
+
+ /**
+ * @return Gets whether this array is mutable.
+ */
+ public boolean isWritable() {
+ enforceNotClosed();
+ return isOwner() || mClientWritable;
+ }
+
+ /**
+ * Gets the value at a given index.
+ *
+ * @param index The index.
+ * @return The value at this index.
+ * @throws IOException If an error occurs while accessing the shared memory.
+ */
+ public int get(int index) throws IOException {
+ enforceNotClosed();
+ enforceValidIndex(index);
+ return nativeGet(mFd.getFd(), mMemoryAddr, index, isOwner());
+ }
+
+ /**
+ * Sets the value at a given index. This method can be called only if
+ * {@link #isWritable()} returns true which means your process is the
+ * owner.
+ *
+ * @param index The index.
+ * @param value The value to set.
+ * @throws IOException If an error occurs while accessing the shared memory.
+ */
+ public void set(int index, int value) throws IOException {
+ enforceNotClosed();
+ enforceWritable();
+ enforceValidIndex(index);
+ nativeSet(mFd.getFd(), mMemoryAddr, index, value, isOwner());
+ }
+
+ /**
+ * Gets the array size.
+ *
+ * @throws IOException If an error occurs while accessing the shared memory.
+ */
+ public int size() throws IOException {
+ enforceNotClosed();
+ return nativeSize(mFd.getFd());
+ }
+
+ /**
+ * Closes the array releasing resources.
+ *
+ * @throws IOException If an error occurs while accessing the shared memory.
+ */
+ @Override
+ public void close() throws IOException {
+ if (!isClosed()) {
+ nativeClose(mFd.getFd(), mMemoryAddr, isOwner());
+ mFd = null;
+ }
+ }
+
+ /**
+ * @return Whether this array is closed and shouldn't be used.
+ */
+ public boolean isClosed() {
+ return mFd == null;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ close();
+ super.finalize();
+ }
+
+ @Override
+ public int describeContents() {
+ return CONTENTS_FILE_DESCRIPTOR;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeInt(mOwnerPid);
+ parcel.writeInt(mClientWritable ? 1 : 0);
+ parcel.writeParcelable(mFd, 0);
+ parcel.writeLong(mMemoryAddr);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ MemoryIntArray other = (MemoryIntArray) obj;
+ if (mFd == null) {
+ if (other.mFd != null) {
+ return false;
+ }
+ } else if (mFd.getFd() != other.mFd.getFd()) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return mFd != null ? mFd.hashCode() : 1;
+ }
+
+ private boolean isOwner() {
+ return mOwnerPid == Process.myPid();
+ }
+
+ private void enforceNotClosed() {
+ if (isClosed()) {
+ throw new IllegalStateException("cannot interact with a closed instance");
+ }
+ }
+
+ private void enforceValidIndex(int index) throws IOException {
+ final int size = size();
+ if (index < 0 || index > size - 1) {
+ throw new IndexOutOfBoundsException(
+ index + " not between 0 and " + (size - 1));
+ }
+ }
+
+ private void enforceWritable() {
+ if (!isWritable()) {
+ throw new UnsupportedOperationException("array is not writable");
+ }
+ }
+
+ private native int nativeCreate(String name, int size);
+ private native long nativeOpen(int fd, boolean owner, boolean writable);
+ private native void nativeClose(int fd, long memoryAddr, boolean owner);
+ private native int nativeGet(int fd, long memoryAddr, int index, boolean owner);
+ private native void nativeSet(int fd, long memoryAddr, int index, int value, boolean owner);
+ private native int nativeSize(int fd);
+ private native static int nativeGetMemoryPageSize();
+
+ /**
+ * @return The max array size.
+ */
+ public static int getMaxSize() {
+ return MAX_SIZE;
+ }
+
+ public static final Parcelable.Creator<MemoryIntArray> CREATOR =
+ new Parcelable.Creator<MemoryIntArray>() {
+ @Override
+ public MemoryIntArray createFromParcel(Parcel parcel) {
+ try {
+ return new MemoryIntArray(parcel);
+ } catch (IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+ }
+
+ @Override
+ public MemoryIntArray[] newArray(int size) {
+ return new MemoryIntArray[size];
+ }
+ };
+}
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index 415c291..cb7c5a2 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -37,6 +37,8 @@
// view hierarchy because display lists are generated recursively.
private static final int POOL_LIMIT = 25;
+ private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB
+
private static final SynchronizedPool<DisplayListCanvas> sPool =
new SynchronizedPool<DisplayListCanvas>(POOL_LIMIT);
@@ -249,4 +251,14 @@
private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
long propRight, long propBottom, long propRx, long propRy, long propPaint);
+
+ @Override
+ protected void throwIfCannotDraw(Bitmap bitmap) {
+ super.throwIfCannotDraw(bitmap);
+ int bitmapSize = bitmap.getByteCount();
+ if (bitmapSize > MAX_BITMAP_SIZE) {
+ throw new RuntimeException(
+ "Canvas: trying to draw too large(" + bitmapSize + "bytes) bitmap.");
+ }
+ }
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2fc1187..5b757d3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5750,9 +5750,9 @@
* view-relative coordinate.
*
* @param x the X coordinate in pixels relative to the view to which the
- * menu should be anchored
+ * menu should be anchored, or {@link Float#NaN} to disable anchoring
* @param y the Y coordinate in pixels relative to the view to which the
- * menu should be anchored
+ * menu should be anchored, or {@link Float#NaN} to disable anchoring
* @return {@code true} if the context menu was shown, {@code false}
* otherwise
*/
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index 06afef2..849c8b9 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -199,9 +199,11 @@
* @param originalView the source view where the context menu was first
* invoked
* @param x the X coordinate in pixels relative to the original view to
- * which the menu should be anchored
+ * which the menu should be anchored, or {@link Float#NaN} to
+ * disable anchoring
* @param y the Y coordinate in pixels relative to the original view to
- * which the menu should be anchored
+ * which the menu should be anchored, or {@link Float#NaN} to
+ * disable anchoring
* @return {@code true} if the context menu was shown, {@code false}
* otherwise
*/
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9e4f26f..a0384f2 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -514,6 +514,34 @@
}
/**
+ * Notifies us that our child has been rebuilt, following
+ * a window preservation operation. In these cases we
+ * keep the same DecorView, but the activity controlling it
+ * is a different instance, and we need to update our
+ * callbacks.
+ *
+ * @hide
+ */
+ public void notifyChildRebuilt() {
+ if (mView instanceof RootViewSurfaceTaker) {
+ mSurfaceHolderCallback =
+ ((RootViewSurfaceTaker)mView).willYouTakeTheSurface();
+ if (mSurfaceHolderCallback != null) {
+ mSurfaceHolder = new TakenSurfaceHolder();
+ mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
+ } else {
+ mSurfaceHolder = null;
+ }
+
+ mInputQueueCallback =
+ ((RootViewSurfaceTaker)mView).willYouTakeTheInputQueue();
+ if (mInputQueueCallback != null) {
+ mInputQueueCallback.onInputQueueCreated(mInputQueue);
+ }
+ }
+ }
+
+ /**
* We have one child
*/
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
@@ -1645,6 +1673,8 @@
boolean insetsPending = false;
int relayoutResult = 0;
+ final int surfaceGenerationId = mSurface.getGenerationId();
+
final boolean isViewVisible = viewVisibility == View.VISIBLE;
if (mFirst || windowShouldResize || insetsChanged ||
viewVisibilityChanged || params != null || mForceNextWindowRelayout) {
@@ -1689,7 +1719,6 @@
}
mChoreographer.mFrameInfo.addFlags(FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED);
}
- final int surfaceGenerationId = mSurface.getGenerationId();
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
if (DEBUG_LAYOUT) Log.v(mTag, "relayout: frame=" + frame.toShortString()
@@ -1883,7 +1912,7 @@
mSurfaceHolder.setSurfaceFrameSize(mWidth, mHeight);
mSurfaceHolder.mSurfaceLock.unlock();
if (mSurface.isValid()) {
- if (!hadSurface) {
+ if (!hadSurface || surfaceGenerationId != mSurface.getGenerationId()) {
mSurfaceHolder.ungetCallbacks();
mIsCreating = true;
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index df506ca..21595d15 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -185,11 +185,12 @@
d.setCallback(this);
d.setVisible(getVisibility() == VISIBLE, false);
d.setState(CHECKED_STATE_SET);
- setMinHeight(d.getIntrinsicHeight());
+ // Record the intrinsic dimensions when in "checked" state.
+ setMinHeight(d.getIntrinsicHeight());
mCheckMarkWidth = d.getIntrinsicWidth();
+
d.setState(getDrawableState());
- applyCheckMarkTint();
} else {
mCheckMarkWidth = 0;
}
@@ -197,6 +198,8 @@
mCheckMarkDrawable = d;
mCheckMarkResource = resId;
+ applyCheckMarkTint();
+
// Do padding resolution. This will call internalSetPadding() and do a
// requestLayout() if needed.
resolvePadding();
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index c6bf1b4..a09dbe5 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -505,6 +505,9 @@
mContextView.killMode();
ActionModeImpl mode = new ActionModeImpl(mContextView.getContext(), callback);
if (mode.dispatchOnCreate()) {
+ // This needs to be set before invalidate() so that it calls
+ // onPrepareActionMode()
+ mActionMode = mode;
mode.invalidate();
mContextView.initForMode(mode);
animateToMode(true);
@@ -518,7 +521,6 @@
}
}
mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- mActionMode = mode;
return mode;
}
return null;
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 3aa7719..645ffda 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -733,16 +733,16 @@
@Override
public boolean showContextMenuForChild(View originalView) {
- return showContextMenuForChildInternal(originalView, 0, 0, false);
+ return showContextMenuForChildInternal(originalView, Float.NaN, Float.NaN);
}
@Override
public boolean showContextMenuForChild(View originalView, float x, float y) {
- return showContextMenuForChildInternal(originalView, x, y, true);
+ return showContextMenuForChildInternal(originalView, x, y);
}
private boolean showContextMenuForChildInternal(View originalView,
- float x, float y, boolean isPopup) {
+ float x, float y) {
// Only allow one context menu at a time.
if (mWindow.mContextMenuHelper != null) {
mWindow.mContextMenuHelper.dismiss();
@@ -759,6 +759,7 @@
}
final MenuHelper helper;
+ final boolean isPopup = !Float.isNaN(x) && !Float.isNaN(y);
if (isPopup) {
helper = mWindow.mContextMenu.showPopup(getContext(), originalView, x, y);
} else {
diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
index 72ed9d0..07f3801 100644
--- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
@@ -349,21 +349,18 @@
final LayoutInflater inflater = LayoutInflater.from(mContext);
final MenuAdapter adapter = new MenuAdapter(menu, inflater, mOverflowOnly);
- // Apply "force show icon" setting. There are 4 cases:
- // (1) This is the top level menu. Only add spacing for icons if forced.
+ // Apply "force show icon" setting. There are 3 cases:
+ // (1) This is the top level menu and icon spacing is forced. Add spacing.
// (2) This is a submenu. Add spacing if any of the visible menu items has an icon.
- // (3) This is a top level menu that is not an overflow menu. Add spacing if any of the
- // visible menu items has an icon.
- // (4) This is an overflow menu or a top level menu that doesn't have "force" set.
- // Don't allow spacing.
+ // (3) This is the top level menu and icon spacing isn't forced. Do not add spacing.
if (!isShowing() && mForceShowIcon) {
// Case 1
adapter.setForceShowIcon(true);
- } else if (isShowing() || !isShowing() && !mForceShowIcon && !mOverflowOnly) {
- // Case 2 or 3
+ } else if (isShowing()) {
+ // Case 2
adapter.setForceShowIcon(MenuPopup.shouldPreserveIconSpacing(menu));
}
- // Case 4: Else, don't allow spacing for icons.
+ // Case 3: Else, don't allow spacing for icons (default behavior; do nothing).
final int menuWidth = measureIndividualMenuWidth(adapter, null, mContext, mMenuMaxWidth);
final MenuPopupWindow popupWindow = createPopupWindow();
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 1f1e594..324f923 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -23,10 +23,13 @@
import android.annotation.Nullable;
import android.annotation.StyleRes;
import android.content.Context;
+import android.graphics.Point;
import android.graphics.Rect;
import android.util.DisplayMetrics;
+import android.view.Display;
import android.view.Gravity;
import android.view.View;
+import android.view.WindowManager;
import android.widget.PopupWindow.OnDismissListener;
/**
@@ -104,6 +107,9 @@
*/
public void setForceShowIcon(boolean forceShowIcon) {
mForceShowIcon = forceShowIcon;
+ if (mPopup != null) {
+ mPopup.setForceShowIcon(forceShowIcon);
+ }
}
/**
@@ -206,8 +212,16 @@
*/
@NonNull
private MenuPopup createPopup() {
- final boolean enableCascadingSubmenus = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_enableCascadingSubmenus);
+ final WindowManager windowManager = (WindowManager) mContext.getSystemService(
+ Context.WINDOW_SERVICE);
+ final Display display = windowManager.getDefaultDisplay();
+ final Point displaySize = new Point();
+ display.getRealSize(displaySize);
+
+ final int smallestWidth = Math.min(displaySize.x, displaySize.y);
+ final int minSmallestWidthCascading = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.cascading_menus_min_smallest_width);
+ final boolean enableCascadingSubmenus = smallestWidth >= minSmallestWidthCascading;
final MenuPopup popup;
if (enableCascadingSubmenus) {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 8a512a6..06d9b29 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -95,6 +95,7 @@
android_util_AssetManager.cpp \
android_util_Binder.cpp \
android_util_EventLog.cpp \
+ android_util_MemoryIntArray.cpp \
android_util_Log.cpp \
android_util_PathParser.cpp \
android_util_Process.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index d3dca5d9..a6a4f6b 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -113,6 +113,7 @@
extern int register_android_content_AssetManager(JNIEnv* env);
extern int register_android_util_EventLog(JNIEnv* env);
extern int register_android_util_Log(JNIEnv* env);
+extern int register_android_util_MemoryIntArray(JNIEnv* env);
extern int register_android_util_PathParser(JNIEnv* env);
extern int register_android_content_StringBlock(JNIEnv* env);
extern int register_android_content_XmlBlock(JNIEnv* env);
@@ -1256,6 +1257,7 @@
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
REG_JNI(register_android_util_Log),
+ REG_JNI(register_android_util_MemoryIntArray),
REG_JNI(register_android_util_PathParser),
REG_JNI(register_android_app_admin_SecurityLog),
REG_JNI(register_android_content_AssetManager),
diff --git a/core/jni/android_util_MemoryIntArray.cpp b/core/jni/android_util_MemoryIntArray.cpp
new file mode 100644
index 0000000..dbe8ed3
--- /dev/null
+++ b/core/jni/android_util_MemoryIntArray.cpp
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "core_jni_helpers.h"
+#include <cutils/ashmem.h>
+#include <sys/mman.h>
+
+namespace android {
+
+static jint android_util_MemoryIntArray_create(JNIEnv* env, jobject clazz, jstring name,
+ jint size)
+{
+ if (name == NULL) {
+ jniThrowException(env, "java/io/IOException", "bad name");
+ return -1;
+ }
+
+ if (size <= 0) {
+ jniThrowException(env, "java/io/IOException", "bad size");
+ return -1;
+ }
+
+ const char* nameStr = env->GetStringUTFChars(name, NULL);
+ const int ashmemSize = sizeof(std::atomic_int) * size;
+ int fd = ashmem_create_region(nameStr, ashmemSize);
+ env->ReleaseStringUTFChars(name, nameStr);
+
+ if (fd < 0) {
+ jniThrowException(env, "java/io/IOException", "ashmem creation failed");
+ return -1;
+ }
+
+ if (ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) {
+ jniThrowException(env, "java/io/IOException", "ashmem was purged");
+ return -1;
+ }
+
+ int setProtResult = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
+ if (setProtResult < 0) {
+ jniThrowException(env, "java/io/IOException", "cannot set ashmem prot mode");
+ return -1;
+ }
+
+ return fd;
+}
+
+static jlong android_util_MemoryIntArray_open(JNIEnv* env, jobject clazz, jint fd,
+ jboolean owner, jboolean writable)
+{
+ if (fd < 0) {
+ jniThrowException(env, "java/io/IOException", "bad file descriptor");
+ return -1;
+ }
+
+ int ashmemSize = ashmem_get_size_region(fd);
+ if (ashmemSize <= 0) {
+ jniThrowException(env, "java/io/IOException", "bad ashmem size");
+ return -1;
+ }
+
+ int protMode = (owner || writable) ? (PROT_READ | PROT_WRITE) : PROT_READ;
+ void* ashmemAddr = mmap(NULL, ashmemSize, protMode, MAP_SHARED, fd, 0);
+ if (ashmemAddr == MAP_FAILED) {
+ jniThrowException(env, "java/io/IOException", "cannot mmap ashmem");
+ return -1;
+ }
+
+ if (owner) {
+ int size = ashmemSize / sizeof(std::atomic_int);
+ new (ashmemAddr) std::atomic_int[size];
+ }
+
+ if (owner && !writable) {
+ int setProtResult = ashmem_set_prot_region(fd, PROT_READ);
+ if (setProtResult < 0) {
+ jniThrowException(env, "java/io/IOException", "cannot set ashmem prot mode");
+ return -1;
+ }
+ }
+
+ return reinterpret_cast<jlong>(ashmemAddr);
+}
+
+static void android_util_MemoryIntArray_close(JNIEnv* env, jobject clazz, jint fd,
+ jlong ashmemAddr, jboolean owner)
+{
+ if (fd < 0) {
+ jniThrowException(env, "java/io/IOException", "bad file descriptor");
+ return;
+ }
+
+ int ashmemSize = ashmem_get_size_region(fd);
+ if (ashmemSize <= 0) {
+ jniThrowException(env, "java/io/IOException", "bad ashmem size");
+ return;
+ }
+
+ int unmapResult = munmap(reinterpret_cast<void *>(ashmemAddr), ashmemSize);
+ if (unmapResult < 0) {
+ jniThrowException(env, "java/io/IOException", "munmap failed");
+ return;
+ }
+
+ // We don't deallocate the atomic ints we created with placement new in the ashmem
+ // region as the kernel we reclaim all pages when the ashmem region is destroyed.
+ if (owner && (ashmem_unpin_region(fd, 0, 0) != ASHMEM_IS_UNPINNED)) {
+ jniThrowException(env, "java/io/IOException", "ashmem unpinning failed");
+ return;
+ }
+
+ close(fd);
+}
+
+static jint android_util_MemoryIntArray_get(JNIEnv* env, jobject clazz,
+ jint fd, jlong address, jint index, jboolean owner)
+{
+ if (fd < 0) {
+ jniThrowException(env, "java/io/IOException", "bad file descriptor");
+ return -1;
+ }
+
+ bool unpin = false;
+
+ if (!owner) {
+ if (ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) {
+ jniThrowException(env, "java/io/IOException", "ashmem region was purged");
+ return -1;
+ }
+ unpin = true;
+ }
+
+ std::atomic_int* value = reinterpret_cast<std::atomic_int*>(address) + index;
+ const int result = value->load(std::memory_order_relaxed);
+
+ if (unpin) {
+ ashmem_unpin_region(fd, 0, 0);
+ }
+
+ return result;
+}
+
+static void android_util_MemoryIntArray_set(JNIEnv* env, jobject clazz,
+ jint fd, jlong address, jint index, jint newValue, jboolean owner)
+{
+ if (fd < 0) {
+ jniThrowException(env, "java/io/IOException", "bad file descriptor");
+ return;
+ }
+
+ bool unpin = false;
+
+ if (!owner) {
+ if (ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) {
+ jniThrowException(env, "java/io/IOException", "ashmem region was purged");
+ return;
+ }
+ unpin = true;
+ }
+
+ std::atomic_int* value = reinterpret_cast<std::atomic_int*>(address) + index;
+ value->store(newValue, std::memory_order_relaxed);
+
+ if (unpin) {
+ ashmem_unpin_region(fd, 0, 0);
+ }
+}
+
+static jint android_util_MemoryIntArray_size(JNIEnv* env, jobject clazz, jint fd) {
+ if (fd < 0) {
+ jniThrowException(env, "java/io/IOException", "bad file descriptor");
+ return -1;
+ }
+
+ // Use ASHMEM_GET_SIZE to find out if the fd refers to an ashmem region.
+ // ASHMEM_GET_SIZE should succeed for all ashmem regions, and the kernel
+ // should return ENOTTY for all other valid file descriptors
+ int ashmemSize = ashmem_get_size_region(fd);
+ if (ashmemSize < 0) {
+ if (errno == ENOTTY) {
+ // ENOTTY means that the ioctl does not apply to this object,
+ // i.e., it is not an ashmem region.
+ return -1;
+ }
+ // Some other error, throw exception
+ jniThrowIOException(env, errno);
+ return -1;
+ }
+ return ashmemSize / sizeof(std::atomic_int);
+}
+
+static const JNINativeMethod methods[] = {
+ {"nativeCreate", "(Ljava/lang/String;I)I", (void*)android_util_MemoryIntArray_create},
+ {"nativeOpen", "(IZZ)J", (void*)android_util_MemoryIntArray_open},
+ {"nativeClose", "(IJZ)V", (void*)android_util_MemoryIntArray_close},
+ {"nativeGet", "(IJIZ)I", (void*)android_util_MemoryIntArray_get},
+ {"nativeSet", "(IJIIZ)V", (void*) android_util_MemoryIntArray_set},
+ {"nativeSize", "(I)I", (void*) android_util_MemoryIntArray_size},
+};
+
+int register_android_util_MemoryIntArray(JNIEnv* env)
+{
+ return RegisterMethodsOrDie(env, "android/util/MemoryIntArray", methods, NELEM(methods));
+}
+
+}
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index d3e18ed..a6db0f4 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -562,6 +562,16 @@
bounds.top -= info.windowInsetTop;
bounds.bottom -= info.windowInsetTop;
+ if (CC_LIKELY(transform.isPureTranslate())) {
+ // snap/round the computed bounds, so they match the rounding behavior
+ // of the clear done in SurfaceView#draw().
+ bounds.snapToPixelBoundaries();
+ } else {
+ // Conservatively round out so the punched hole (in the ZOrderOnTop = true case)
+ // doesn't extend beyond the other window
+ bounds.roundOut();
+ }
+
auto functor = std::bind(
std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePosition), this,
(jlong) info.canvasContext.getFrameNumber(),
diff --git a/core/res/res/values-sw720dp/config.xml b/core/res/res/values-sw720dp/config.xml
index 1f5791a..9792835 100644
--- a/core/res/res/values-sw720dp/config.xml
+++ b/core/res/res/values-sw720dp/config.xml
@@ -19,7 +19,4 @@
used for picking activities to handle an intent. -->
<integer name="config_maxResolverActivityColumns">4</integer>
- <!-- Enable cascading submenus. -->
- <bool name="config_enableCascadingSubmenus">true</bool>
-
</resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index e040bea..cd7df87 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -552,6 +552,15 @@
should not be interrupted with other activities or notifications. -->
<attr name="immersive" format="boolean" />
+ <!-- Flag declaring that this activity will be run in VR mode, and specifying
+ the component of the VrListenerService that should be bound while this
+ Activity is visible if installed and enabled on this device. This is
+ equivalent to calling {@link android.app.Activity#setVrModeEnabled} with the
+ the given component name within this Activity. Declaring this will prevent
+ the system from leaving VR mode during an Activity transtion one VR activity
+ to another. -->
+ <attr name="enableVrMode" format="string" />
+
<!-- Specify the order in which content providers hosted by a process
are instantiated when that process is created. Not needed unless
you have providers with dependencies between each other, to make
@@ -1884,6 +1893,7 @@
For example, {@link android.R.attr#supportsPictureInPicture} activities are placed
in a task/stack that isn't focusable. This flag allows them to be focusable.-->
<attr name="alwaysFocusable" format="boolean" />
+ <attr name="enableVrMode" />
</declare-styleable>
<!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 789a417..e73fa9a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2380,10 +2380,6 @@
must match the value of config_cameraLaunchGestureSensorType in OEM's HAL -->
<string translatable="false" name="config_cameraLaunchGestureSensorStringType"></string>
- <!-- Whether to open UI submenus side by side with the top menu (as opposed to
- replacing the top menu). -->
- <bool name="config_enableCascadingSubmenus">false</bool>
-
<!-- Allow the gesture to double tap the power button twice to start the camera while the device
is non-interactive. -->
<bool name="config_cameraDoubleTapPowerGestureEnabled">true</bool>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 5446d4c..8ce922e 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -468,4 +468,7 @@
<!-- The default minimal size of a resizable task, in both dimensions. -->
<dimen name="default_minimal_size_resizable_task">220dp</dimen>
+
+ <!-- Minimum "smallest width" of the display for cascading menus to be enabled. -->
+ <dimen name="cascading_menus_min_smallest_width">720dp</dimen>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 80b3a64..11df8e5 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2714,6 +2714,7 @@
<public type="attr" name="contentInsetStartWithNavigation" />
<public type="attr" name="contentInsetEndWithActions" />
<public type="attr" name="numberPickerStyle" />
+ <public type="attr" name="enableVrMode" />
<public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
<public type="style" name="Widget.Material.SeekBar.Discrete" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 22b6b75..4d86a92 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2256,7 +2256,8 @@
<java-symbol type="string" name="prohibit_manual_network_selection_in_gobal_mode" />
<java-symbol type="id" name="profile_button" />
- <java-symbol type="bool" name="config_enableCascadingSubmenus" />
+ <!-- Cascading submenus -->
+ <java-symbol type="dimen" name="cascading_menus_min_smallest_width" />
<!-- From SignalStrength -->
<java-symbol type="integer" name="config_LTE_RSRP_threshold_type" />
diff --git a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
new file mode 100644
index 0000000..6b31916
--- /dev/null
+++ b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.os.Parcel;
+import junit.framework.TestCase;
+import libcore.io.IoUtils;
+
+public class MemoryIntArrayTest extends TestCase {
+
+ public void testSize() throws Exception {
+ MemoryIntArray array = null;
+ try {
+ array = new MemoryIntArray(3, false);
+ assertEquals("size must be three", 3, array.size());
+ } finally {
+ IoUtils.closeQuietly(array);
+ }
+ }
+
+ public void testGetSet() throws Exception {
+ MemoryIntArray array = null;
+ try {
+ array = new MemoryIntArray(3, false);
+
+ array.set(0, 1);
+ array.set(1, 2);
+ array.set(2, 3);
+
+ assertEquals("First element should be 1", 1, array.get(0));
+ assertEquals("First element should be 2", 2, array.get(1));
+ assertEquals("First element should be 3", 3, array.get(2));
+ } finally {
+ IoUtils.closeQuietly(array);
+ }
+ }
+
+ public void testWritable() throws Exception {
+ MemoryIntArray array = null;
+ try {
+ array = new MemoryIntArray(3, true);
+ assertTrue("Must be mutable", array.isWritable());
+ } finally {
+ IoUtils.closeQuietly(array);
+ }
+ }
+
+ public void testClose() throws Exception {
+ MemoryIntArray array = null;
+ try {
+ array = new MemoryIntArray(3, false);
+ array.close();
+ assertTrue("Must be closed", array.isClosed());
+ } finally {
+ if (array != null && !array.isClosed()) {
+ IoUtils.closeQuietly(array);
+ }
+ }
+ }
+
+ public void testMarshalledGetSet() throws Exception {
+ MemoryIntArray firstArray = null;
+ MemoryIntArray secondArray = null;
+ try {
+ firstArray = new MemoryIntArray(3, false);
+
+ firstArray.set(0, 1);
+ firstArray.set(1, 2);
+ firstArray.set(2, 3);
+
+ Parcel parcel = Parcel.obtain();
+ parcel.writeParcelable(firstArray, 0);
+ parcel.setDataPosition(0);
+ secondArray = parcel.readParcelable(null);
+ parcel.recycle();
+
+ assertNotNull("Should marshall file descriptor", secondArray);
+
+ assertEquals("First element should be 1", 1, secondArray.get(0));
+ assertEquals("First element should be 2", 2, secondArray.get(1));
+ assertEquals("First element should be 3", 3, secondArray.get(2));
+ } finally {
+ IoUtils.closeQuietly(firstArray);
+ IoUtils.closeQuietly(secondArray);
+ }
+ }
+
+ public void testInteractOnceClosed() throws Exception {
+ MemoryIntArray array = null;
+ try {
+ array = new MemoryIntArray(3, false);
+ array.close();
+
+ array.close();
+
+ try {
+ array.size();
+ fail("Cannot interact with a closed instance");
+ } catch (IllegalStateException e) {
+ /* expected */
+ }
+
+ try {
+ array.get(0);
+ fail("Cannot interact with a closed instance");
+ } catch (IllegalStateException e) {
+ /* expected */
+ }
+
+ try {
+ array.set(0, 1);
+ fail("Cannot interact with a closed instance");
+ } catch (IllegalStateException e) {
+ /* expected */
+ }
+
+ try {
+ array.isWritable();
+ fail("Cannot interact with a closed instance");
+ } catch (IllegalStateException e) {
+ /* expected */
+ }
+ } finally {
+ if (array != null && !array.isClosed()) {
+ IoUtils.closeQuietly(array);
+ }
+ }
+ }
+
+ public void testInteractPutOfBounds() throws Exception {
+ MemoryIntArray array = null;
+ try {
+ array = new MemoryIntArray(3, false);
+
+ try {
+ array.get(-1);
+ fail("Cannot interact out of array bounds");
+ } catch (IndexOutOfBoundsException e) {
+ /* expected */
+ }
+
+ try {
+ array.get(3);
+ fail("Cannot interact out of array bounds");
+ } catch (IndexOutOfBoundsException e) {
+ /* expected */
+ }
+
+ try {
+ array.set(-1, 0);
+ fail("Cannot interact out of array bounds");
+ } catch (IndexOutOfBoundsException e) {
+ /* expected */
+ }
+
+ try {
+ array.set(3, 0);
+ fail("Cannot interact out of array bounds");
+ } catch (IndexOutOfBoundsException e) {
+ /* expected */
+ }
+ } finally {
+ IoUtils.closeQuietly(array);
+ }
+ }
+
+ public void testOverMaxSize() throws Exception {
+ MemoryIntArray array = null;
+ try {
+ array = new MemoryIntArray(MemoryIntArray.getMaxSize() + 1, false);
+ fail("Cannot use over max size");
+ } catch (IllegalArgumentException e) {
+ /* expected */
+ } finally {
+ IoUtils.closeQuietly(array);
+ }
+ }
+}
diff --git a/docs/html/develop/index.jd b/docs/html/develop/index.jd
index 460d056..49235ae 100644
--- a/docs/html/develop/index.jd
+++ b/docs/html/develop/index.jd
@@ -9,7 +9,7 @@
excludeFromSuggestions=true
@jd:body
-<section class="dac-expand dac-hero dac-section-light">
+<section class="dac-expand dac-hero dac-section-light" style="background:#FFE57F">
<div class="wrap">
<div class="cols dac-hero-content">
<div class="col-1of2 col-push-1of2 dac-hero-figure">
@@ -19,30 +19,37 @@
frameborder="0" allowfullscreen=""
style="float: right;"></iframe>
-->
- <img class="dac-hero-image" src="{@docRoot}images/develop/hero_image_studio5_2x.png"
- srcset="/images/develop/hero_image_studio5.png 1x, /images/develop/hero_image_studio5_2x.png 2x" />
+ <img class="dac-hero-image" src="{@docRoot}images/tools/studio/studio-feature-instant-run_2x.png" />
</div>
<div class="col-1of2 col-pull-1of2">
- <h1 class="dac-hero-title">Get Started with Android Studio</h1>
+ <h1 class="dac-hero-title">Android Studio 2.0,<br>now available!</h1>
<p class="dac-hero-description">
- Everything you need to build incredible app experiences on phones and tablets, Wear, TV, and Auto. </p>
+ The latest version of Android Studio is the biggest update yet.
+ It includes new features like <strong>Instant Run</strong>, which
+ dramatically speeds up your edit, build, and run cycles, keeping
+ you "in the flow."</p>
</p>
- <a class="dac-hero-cta" href="{@docRoot}sdk/index.html">
- <span class="dac-sprite dac-auto-chevron"></span>
- Set up Android Studio
- </a><br>
- <a class="dac-hero-cta" href="{@docRoot}training/index.html">
- <span class="dac-sprite dac-auto-chevron"></span>
- Build your first app
- </a><br>
- <a class="dac-hero-cta" href="{@docRoot}guide/index.html">
- <span class="dac-sprite dac-auto-chevron"></span>
- Learn about Android
- </a><br>
- <a class="dac-hero-cta" href="{@docRoot}samples/index.html">
- <span class="dac-sprite dac-auto-chevron"></span>
- Sample projects
- </a><br>
+ <div class="cols">
+ <div class="col-1of2">
+ <a class="dac-hero-cta" href="{@docRoot}sdk/index.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Get Android Studio
+ </a><br>
+ <a class="dac-hero-cta" href="{@docRoot}training/index.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Build your first app
+ </a>
+ </div>
+ <div class="col-1of2">
+ <a class="dac-hero-cta" href="{@docRoot}guide/index.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Learn about Android
+ </a><br>
+ <a class="dac-hero-cta" href="{@docRoot}samples/index.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ See sample projects
+ </a>
+ </div>
</div>
</div>
<!--<div class="dac-section dac-small">
diff --git a/docs/html/images/studio-avdmgr-firstscreen.png b/docs/html/images/studio-avdmgr-firstscreen.png
deleted file mode 100644
index 5da5c6c..0000000
--- a/docs/html/images/studio-avdmgr-firstscreen.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/images/studio-avdmgr-selecthdwr.png b/docs/html/images/studio-avdmgr-selecthdwr.png
deleted file mode 100644
index 015833a..0000000
--- a/docs/html/images/studio-avdmgr-selecthdwr.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/images/tools/ai-appindexingtest.png b/docs/html/images/tools/ai-appindexingtest.png
new file mode 100644
index 0000000..385bc21
--- /dev/null
+++ b/docs/html/images/tools/ai-appindexingtest.png
Binary files differ
diff --git a/docs/html/images/tools/as-cleanrerun.png b/docs/html/images/tools/as-cleanrerun.png
new file mode 100644
index 0000000..7d57b0f
--- /dev/null
+++ b/docs/html/images/tools/as-cleanrerun.png
Binary files differ
diff --git a/docs/html/images/tools/as-launchavdm.png b/docs/html/images/tools/as-launchavdm.png
index bf15981..f2c7bf3 100644
--- a/docs/html/images/tools/as-launchavdm.png
+++ b/docs/html/images/tools/as-launchavdm.png
Binary files differ
diff --git a/docs/html/images/tools/as-ok.png b/docs/html/images/tools/as-ok.png
new file mode 100644
index 0000000..244a77f
--- /dev/null
+++ b/docs/html/images/tools/as-ok.png
Binary files differ
diff --git a/docs/html/images/tools/as-restart.png b/docs/html/images/tools/as-restart.png
index 12d2923..39122c9 100644
--- a/docs/html/images/tools/as-restart.png
+++ b/docs/html/images/tools/as-restart.png
Binary files differ
diff --git a/docs/html/images/tools/as-stop.png b/docs/html/images/tools/as-stop.png
new file mode 100644
index 0000000..ed1424b
--- /dev/null
+++ b/docs/html/images/tools/as-stop.png
Binary files differ
diff --git a/docs/html/images/tools/as-wrench.png b/docs/html/images/tools/as-wrench.png
new file mode 100644
index 0000000..5886487
--- /dev/null
+++ b/docs/html/images/tools/as-wrench.png
Binary files differ
diff --git a/docs/html/images/tools/avd-configurehp.png b/docs/html/images/tools/avd-configurehp.png
new file mode 100644
index 0000000..e053364
--- /dev/null
+++ b/docs/html/images/tools/avd-configurehp.png
Binary files differ
diff --git a/docs/html/images/tools/avd-hardwareprofile.png b/docs/html/images/tools/avd-hardwareprofile.png
new file mode 100644
index 0000000..f4b6b46
--- /dev/null
+++ b/docs/html/images/tools/avd-hardwareprofile.png
Binary files differ
diff --git a/docs/html/images/tools/avd-main.png b/docs/html/images/tools/avd-main.png
new file mode 100644
index 0000000..f326002
--- /dev/null
+++ b/docs/html/images/tools/avd-main.png
Binary files differ
diff --git a/docs/html/images/tools/avd-systemimage.png b/docs/html/images/tools/avd-systemimage.png
new file mode 100644
index 0000000..7026d84
--- /dev/null
+++ b/docs/html/images/tools/avd-systemimage.png
Binary files differ
diff --git a/docs/html/images/tools/avd-verifyconfig.png b/docs/html/images/tools/avd-verifyconfig.png
new file mode 100644
index 0000000..cd76690
--- /dev/null
+++ b/docs/html/images/tools/avd-verifyconfig.png
Binary files differ
diff --git a/docs/html/images/tools/e-dpad.png b/docs/html/images/tools/e-dpad.png
new file mode 100644
index 0000000..1fb9500
--- /dev/null
+++ b/docs/html/images/tools/e-dpad.png
Binary files differ
diff --git a/docs/html/images/tools/e-emulator.png b/docs/html/images/tools/e-emulator.png
new file mode 100644
index 0000000..4b758b9
--- /dev/null
+++ b/docs/html/images/tools/e-emulator.png
Binary files differ
diff --git a/docs/html/images/tools/e-iback.png b/docs/html/images/tools/e-iback.png
new file mode 100644
index 0000000..ca9b984
--- /dev/null
+++ b/docs/html/images/tools/e-iback.png
Binary files differ
diff --git a/docs/html/images/tools/e-iclose.png b/docs/html/images/tools/e-iclose.png
new file mode 100644
index 0000000..00ecfad
--- /dev/null
+++ b/docs/html/images/tools/e-iclose.png
Binary files differ
diff --git a/docs/html/images/tools/e-ihome.png b/docs/html/images/tools/e-ihome.png
new file mode 100644
index 0000000..a6ce33e
--- /dev/null
+++ b/docs/html/images/tools/e-ihome.png
Binary files differ
diff --git a/docs/html/images/tools/e-ilocation.png b/docs/html/images/tools/e-ilocation.png
new file mode 100644
index 0000000..2c152a6
--- /dev/null
+++ b/docs/html/images/tools/e-ilocation.png
Binary files differ
diff --git a/docs/html/images/tools/e-iminimize.png b/docs/html/images/tools/e-iminimize.png
new file mode 100644
index 0000000..6633539
--- /dev/null
+++ b/docs/html/images/tools/e-iminimize.png
Binary files differ
diff --git a/docs/html/images/tools/e-imore.png b/docs/html/images/tools/e-imore.png
new file mode 100644
index 0000000..dec8902
--- /dev/null
+++ b/docs/html/images/tools/e-imore.png
Binary files differ
diff --git a/docs/html/images/tools/e-ioverview.png b/docs/html/images/tools/e-ioverview.png
new file mode 100644
index 0000000..828d2a5
--- /dev/null
+++ b/docs/html/images/tools/e-ioverview.png
Binary files differ
diff --git a/docs/html/images/tools/e-ipower.png b/docs/html/images/tools/e-ipower.png
new file mode 100644
index 0000000..e08a5bb
--- /dev/null
+++ b/docs/html/images/tools/e-ipower.png
Binary files differ
diff --git a/docs/html/images/tools/e-irotateleft.png b/docs/html/images/tools/e-irotateleft.png
new file mode 100644
index 0000000..07d65f4
--- /dev/null
+++ b/docs/html/images/tools/e-irotateleft.png
Binary files differ
diff --git a/docs/html/images/tools/e-irotateright.png b/docs/html/images/tools/e-irotateright.png
new file mode 100644
index 0000000..939ff4e3
--- /dev/null
+++ b/docs/html/images/tools/e-irotateright.png
Binary files differ
diff --git a/docs/html/images/tools/e-irun.png b/docs/html/images/tools/e-irun.png
new file mode 100644
index 0000000..7247db7
--- /dev/null
+++ b/docs/html/images/tools/e-irun.png
Binary files differ
diff --git a/docs/html/images/tools/e-itakescreenshot.png b/docs/html/images/tools/e-itakescreenshot.png
new file mode 100644
index 0000000..a38d7d9
--- /dev/null
+++ b/docs/html/images/tools/e-itakescreenshot.png
Binary files differ
diff --git a/docs/html/images/tools/e-ivolumedown.png b/docs/html/images/tools/e-ivolumedown.png
new file mode 100644
index 0000000..ef4f386
--- /dev/null
+++ b/docs/html/images/tools/e-ivolumedown.png
Binary files differ
diff --git a/docs/html/images/tools/e-ivolumeup.png b/docs/html/images/tools/e-ivolumeup.png
new file mode 100644
index 0000000..61dff17
--- /dev/null
+++ b/docs/html/images/tools/e-ivolumeup.png
Binary files differ
diff --git a/docs/html/images/tools/e-izoom.png b/docs/html/images/tools/e-izoom.png
new file mode 100644
index 0000000..4b702e8
--- /dev/null
+++ b/docs/html/images/tools/e-izoom.png
Binary files differ
diff --git a/docs/html/images/tools/e-selectdeploymenttarget.png b/docs/html/images/tools/e-selectdeploymenttarget.png
new file mode 100644
index 0000000..60c088b
--- /dev/null
+++ b/docs/html/images/tools/e-selectdeploymenttarget.png
Binary files differ
diff --git a/docs/html/images/tools/instant-run/as-irdebug.png b/docs/html/images/tools/instant-run/as-irdebug.png
new file mode 100644
index 0000000..0754afac
--- /dev/null
+++ b/docs/html/images/tools/instant-run/as-irdebug.png
Binary files differ
diff --git a/docs/html/images/tools/instant-run/as-irrun.png b/docs/html/images/tools/instant-run/as-irrun.png
new file mode 100644
index 0000000..8b5fafa
--- /dev/null
+++ b/docs/html/images/tools/instant-run/as-irrun.png
Binary files differ
diff --git a/docs/html/images/tools/instant-run/update-project-dialog.png b/docs/html/images/tools/instant-run/update-project-dialog.png
new file mode 100644
index 0000000..e106c57
--- /dev/null
+++ b/docs/html/images/tools/instant-run/update-project-dialog.png
Binary files differ
diff --git a/docs/html/images/training/ctl-exec-log.png b/docs/html/images/training/ctl-exec-log.png
new file mode 100644
index 0000000..96bbb81
--- /dev/null
+++ b/docs/html/images/training/ctl-exec-log.png
Binary files differ
diff --git a/docs/html/images/training/ctl-test-results.png b/docs/html/images/training/ctl-test-results.png
new file mode 100644
index 0000000..bb2fc93
--- /dev/null
+++ b/docs/html/images/training/ctl-test-results.png
Binary files differ
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 0250c1e..923a6d7 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -503,7 +503,7 @@
<li>2 GB of available disk space minimum (500 MB for IDE + 1.5 GB for
Android SDK and emulator system image). 4 GB Recommended.</li>
<li>1280 x 800 minimum screen resolution</li>
-<li>Java Development Kit (JDK) 8</li>
+<li>Java Development Kit (JDK) 6</li>
</ul>
</div>
diff --git a/docs/html/tools/building/building-studio.jd b/docs/html/tools/building/building-studio.jd
index 2e3615e..6827c57 100644
--- a/docs/html/tools/building/building-studio.jd
+++ b/docs/html/tools/building/building-studio.jd
@@ -7,10 +7,34 @@
<div id="qv">
<h2>In this document</h2>
<ol>
- <li><a href="#run-configuration">Changing the run configuration</a> </li>
- <li><a href="#changing-variant">Changing build variants</a></li>
- <li><a href="#gradle-console">Monitoring the build process</a></li>
- <li><a href="#generating-apks">Generating APKs</a></li>
+ <li>
+ <a href="#run-configuration">Changing the run configuration</a>
+ </li>
+
+ <li>
+ <a href="#changing-variant">Changing build variants</a>
+ </li>
+
+ <li>
+ <a href="#gradle-console">Monitoring the build process</a>
+ </li>
+
+ <li>
+ <a href="#generating-apks">Generating APKs</a>
+ </li>
+
+ <li>
+ <a href="#instant-run">About Instant Run</a>
+ <ol>
+ <li>
+ <a href="#set-up-ir">Configuring and optimizing your project for Instant Run</a>
+ </li>
+
+ <li>
+ <a href="#ir-limitations">Limitations of Instant Run</a>
+ </li>
+ </ol>
+ </li>
</ol>
<h2>See also</h2>
@@ -31,7 +55,9 @@
<p>
By default, Android Studio sets up new projects to deploy to the Emulator or
- a physical device with just a few clicks.
+ a physical device with just a few clicks. With Instant Run, you can push
+ changes to methods and existing app resources to a running app without
+ building a new APK, so code changes are visible almost instantly.
</p>
<p>
@@ -138,8 +164,8 @@
</h3>
<p>
- You can view details about the build process by clicking <em>Gradle
- Console</em> <img src="{@docRoot}images/tools/as-gradlebutton.png" alt=""
+ You can view details about the build process by clicking <strong>Gradle
+ Console</strong> <img src="{@docRoot}images/tools/as-gradlebutton.png" alt=""
style="vertical-align:bottom;margin:0;">. The console displays each
task that Gradle executes in order to build your app, as shown in figure 1.
</p>
@@ -160,7 +186,40 @@
<p>
If an error occurs during the build process, the <em>Messages</em> window
- will appear to describe the issue.
+ appears to describe the issue. Gradle may recommend some command-line
+ options to help you resolve the issue, such as <code>--stacktrace</code> or
+ <code>--debug</code>. To use command-line options with your build process:
+</p>
+
+<ol>
+ <li>Open the <strong>Settings</strong> or <strong>Preferences</strong>
+ dialog:
+ <ul>
+ <li>On Windows or Linux, select <strong>File</strong> >
+ <strong>Settings</strong> from the main menu.
+ </li>
+
+ <li>On Mac OSX, select <strong>Android Studio</strong> >
+ <strong>Preferences</strong> from the main menu.
+ </li>
+ </ul>
+ </li>
+
+ <li>Navigate to <strong>Build, Execution, Deployment</strong> >
+ <strong>Compiler</strong>.
+ </li>
+
+ <li>In the text field next to <em>Command-line Options</em>, enter your
+ command-line options.
+ </li>
+
+ <li>Click <strong>OK</strong> to save and exit.
+ </li>
+</ol>
+
+<p>
+ Gradle will apply these command-line options the next time you try building
+ your app.
</p>
<h3 id="generating-apks">
@@ -184,4 +243,503 @@
<p class="img-caption">
<strong>Figure 2.</strong> Click the link to locate the generated APK
files.
-</p>
\ No newline at end of file
+</p>
+
+<h2 id="instant-run">About Instant Run</h3>
+
+<p>
+ Introduced in Android Studio 2.0, Instant Run is a behavior for the
+ <strong>Run</strong> <img src="{@docRoot}images/tools/as-run.png" alt=""
+ style="vertical-align:bottom;margin:0;"> and <strong>Debug</strong> <img src=
+ "{@docRoot}images/tools/as-debugbutton.png" alt="" style=
+ "vertical-align:bottom;margin:0;"> commands that significantly reduces the
+ time between updates to your app. Although your first build may take longer
+ to complete, Instant Run pushes subsequent updates to your app without
+ building a new APK, so changes are visible much more quickly.
+</p>
+
+<p>
+ Instant Run is supported only when you deploy the debug build variant, use
+ Android Plugin for Gradle version 2.0.0 or higher, and set
+ <code>minSdkVersion</code> to 15 or higher in your app's module-level
+ <code>build.gradle</code> file. For the best performance, set
+ <code>minSdkVersion</code> to 21 or higher.
+</p>
+
+<p>
+ After deploying an app, a small, yellow thunderbolt icon appears within the
+ <strong>Run</strong> <img src=
+ "{@docRoot}images/tools/instant-run/as-irrun.png" alt="" style=
+ "vertical-align:bottom;margin:0;"> button (or <strong>Debug</strong>
+ <img src="{@docRoot}images/tools/instant-run/as-irdebug.png" alt="" style=
+ "vertical-align:bottom;margin:0;"> button), indicating that Instant Run is
+ ready to push updates the next time you click the button. Instead of building
+ a new APK, it pushes just those new changes and, in some cases, the app
+ doesn't even need to restart but immediately shows the effect of those code
+ changes.
+</p>
+
+<p>
+ Instant Run pushes updated code and resources to your connected device or
+ emulator by performing a <em>hot swap</em>, <em>warm swap</em>, or <em>cold
+ swap</em>. It automatically determines the type of swap to perform based on
+ the type of change you made. The following table describes how Instant Run
+ behaves when you push certain code changes to a target device.
+</p>
+
+<table id="ir-table">
+ <col width="40%">
+ <tr>
+ <th scope="col">
+ Code Change
+ </th>
+ <th scope="col">
+ Instant Run Behavior
+ </th>
+ </tr>
+
+ <tr id="hot-swap">
+ <td>
+ <ul>
+ <li>Change implementation code of an existing method
+ </li>
+ </ul>
+ </td>
+ <td>
+ <p>
+ Supported with <strong>hot swap</strong>: This is the
+ fastest type of swap and makes changes visible much more quickly. Your
+ application keeps running and a stub method with the new implementation is used
+ the next time the method is called.
+ </p>
+
+ <p>
+ Hot swaps do not re-initialize objects in your running app. You may need to
+ restart the current activity, or <a href="#rerun">restart the app</a>, before
+ you see certain updates. By default, Android Studio automatically restarts the
+ current activity after performing a hot swap. If you do not want this behavior,
+ you can <a href="#activity-restart">disable automatic activity restarts</a>.
+ </p>
+ </td>
+ </tr>
+
+ <tr id="warm-swap">
+ <td>
+ <ul>
+ <li>Change or remove an existing resource
+ </li>
+ </ul>
+ </td>
+ <td>
+ Supported with <strong>warm swap</strong>: This swap
+ is still very fast, but Instant Run must restart the current activity when it
+ pushes the changed resources to your app. Your app keeps running, but a small
+ flicker may appear on the screen as the activity restarts—this is normal.
+ </td>
+ </tr>
+
+ <tr id="cold-swap">
+ <td>
+ Structural code changes, such as:
+ <ul>
+ <li>Add, remove, or change:
+ <ul>
+ <li>an annotation
+ </li>
+
+ <li>an instance field
+ </li>
+
+ <li>a static field
+ </li>
+
+ <li>a static method signature
+ </li>
+
+ <li>an instance method signature
+ </li>
+ </ul>
+ </li>
+
+ <li>Change which parent class the current class inherits from
+ </li>
+
+ <li>Change the list of implemented interfaces
+ </li>
+
+ <li>Change a class's static initializer
+ </li>
+
+ <li>Reorder layout elements that use dynamic resource IDs
+ </li>
+ </ul>
+ </td>
+ <td>
+ <p>
+ Supported with <strong>cold swap</strong> (API level 21 or higher): This swap
+ is a bit slower because, although a new APK is not required, Instant Run must
+ restart the whole app when it pushes structural code changes.
+ </p>
+
+ <p>
+ For target devices running API level 20 or lower, Android Studio
+ deploys a full APK.
+ </p>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <ul>
+ <li>Change the app manifest
+ </li>
+
+ <li>Change resources reference by the app manifest
+ </li>
+
+ <li>Change an Android widget UI element (requires a <a href="#rerun">
+ Clean and Rerun</a>)
+ </li>
+ </ul>
+ </td>
+ <td>
+ <p>
+ When making changes to the app's manifest or resources referenced by the
+ manifest, Android Studio automatically <strong>deploys a new build</strong>
+ in order to apply these changes. This is because certain information about
+ the app, such as its name, app icon resources, and intent filters, are
+ determined from the manifest when the APK is installed on the device.
+ </p>
+
+ <p>
+ If your build process automatically updates any part of the app manifest,
+ such as automatically iterating <code>versionCode</code> or
+ <code>versionName</code>, you will not be able to benefit from the full
+ performance of Instant Run. We recommend that you disable automatic updates
+ to any part in the app manifest in your debug build variants.
+ </p>
+ </td>
+ </tr>
+</table>
+
+<p class="note">
+ <strong>Note:</strong> If you need to restart your app after a crash, do not
+ launch it from your target device. Restarting your app from your target
+ device does not apply any of your code changes since the last cold swap or
+ <em>incremental build</em>. To launch your app with all your recent changes,
+ click <strong>Run</strong> <img src="{@docRoot}images/tools/as-run.png" alt=
+ "" style="vertical-align:bottom;margin:0;"> (or <strong>Debug</strong>
+ <img src="{@docRoot}images/tools/as-debugbutton.png" alt="" style=
+ "vertical-align:bottom;margin:0;">) from Android Studio.
+</p>
+
+<h4 id="rerun">
+ Using Rerun
+</h4>
+
+<p>
+ When pushing code changes that affect certain initializers, such as changes
+ to an app's {@link android.app.Application#onCreate onCreate()} method, you
+ need to restart your app for the changes to take effect. To perform an
+ <em>incremental build</em> and restart the app, click <strong>Rerun</strong>
+ <img src="{@docRoot}images/tools/as-restart.png" alt="" style=
+ "vertical-align:bottom;margin:0;">.
+</p>
+
+<p>
+ If you need to deploy a <em>clean build</em>, select <strong>Run</strong>
+ > <strong>Clean and Rerun 'app'</strong> <img src=
+ "{@docRoot}images/tools/as-cleanrerun.png" alt="" style=
+ "vertical-align:bottom;margin:0;"> from the main menu, or hold down the
+ <strong>Shift</strong> key while clicking <strong>Rerun</strong> <img src=
+ "{@docRoot}images/tools/as-restart.png" alt="" style=
+ "vertical-align:bottom;margin:0;">. This action stops the running app,
+ performs a full clean build, and deploys the new APK to your target device.
+</p>
+
+<h4 id="activity-restart">
+ Disabling automatic activity restart
+</h4>
+
+<p>
+ When performing a hot swap, your app keeps running but Android Studio
+ automatically restarts the current activity. To disable this default setting:
+</p>
+
+<ol>
+ <li>Open the <strong>Settings</strong> or <strong>Preferences</strong>
+ dialog:
+ <ul>
+ <li>On Windows or Linux, select <strong>File</strong> >
+ <strong>Settings</strong> from the main menu.
+ </li>
+
+ <li>On Mac OSX, select <strong>Android Studio</strong> >
+ <strong>Preferences</strong> from the main menu.
+ </li>
+ </ul>
+ </li>
+
+ <li>Navigate to <strong>Build, Execution, Deployment</strong> >
+ <strong>Instant Run</strong>.
+ </li>
+
+ <li>Uncheck the box next to <strong>Restart activity on code
+ changes</strong>.
+ </li>
+</ol>
+
+<p>
+ If automatic activity restart is disabled, you can manually restart the current
+ activity from the menu bar by selecting <strong>Run</strong> > <strong>Restart
+ Activity</strong>.
+</p>
+
+<h3 id="set-up-ir">
+ Configuring and optimizing your project for Instant Run
+</h3>
+
+<p>
+ Android Studio enables Instant Run by default for projects built using
+ Android Plugin for Gradle 2.0.0 and higher.
+</p>
+
+<p>
+ To update an existing project with the latest version of the plugin:
+</p>
+
+<ol>
+ <li>Open the <strong>Settings</strong> or <strong>Preferences</strong>
+ dialog.
+ </li>
+
+ <li>
+ <p>
+ Navigate to <strong>Build, Execution, Deployment</strong> >
+ <strong>Instant Run</strong> and click <strong>Update Project</strong>,
+ as shown in figure 3.
+ </p>
+
+ <p>
+ If the option to update the project does not appear, it’s already
+ up-to-date with the latest Android Plugin for Gradle.
+ </p>
+
+ <img src="{@docRoot}images/tools/instant-run/update-project-dialog.png"
+ alt="" height="51">
+
+ <p class="img-caption">
+ <strong>Figure 3.</strong> Updating the Android Plugin for Gradle for an
+ existing project.
+ </p>
+ </li>
+</ol>
+
+<p>
+ You also need to <a href="#changing-variant">change the build variant</a> to
+ a debug version of your app to start using Instant Run.
+</p>
+
+<h4 id="configure-dexoptions">
+ Improve build times by configuring DEX resources
+</h4>
+
+<p>
+ When you deploy a clean build, Android Studio instruments your app to allow
+ Instant Run to push code and resource updates. Although updating the running
+ app happens much more quickly, the first build may take longer to complete.
+ You can improve the build process by configuring a few DEX options, such as
+ <code>maxProcessCount</code> and <code>javaMaxHeapSize</code>.
+</p>
+
+<dl>
+ <dt>
+ <code>maxProcessCount</code>
+ </dt>
+
+ <dd>
+ Sets the maximum number of DEX processes that can be started
+ concurrently. If the Gradle daemon is already running, you need to
+ stop the process before initializing it with a new maximum process count.
+ You can terminate the Gradle daemon by calling one of the following from
+ the <em>Terminal</em> window:
+ <ul>
+ <li>On Windows, call <code>gradlew --stop</code>
+ </li>
+
+ <li>On Linux/Mac OSX, call <code>./gradlew --stop</code>
+ </li>
+ </ul>
+ </dd>
+
+ <dt>
+ <code>javaMaxHeapSize</code>
+ </dt>
+
+ <dd>
+ Sets the maximum memory allocation pool size for the dex operation. When
+ passing a value, you can append the letter 'k' to indicate kilobytes, 'm'
+ to indicate megabytes, or 'g' to indicate gigabytes.
+ </dd>
+</dl>
+
+<p>
+ The following example sets <code>maxProcessCount</code> to 4 and
+ <code>javaMaxHeapSize</code> to "2g" in the module-level
+ <code>build.gradle</code> file:
+</p>
+
+<pre>
+android {
+ ...
+ dexOptions {
+ maxProcessCount 8
+ javaMaxHeapSize "2g"
+ }
+}
+</pre>
+
+<p>
+ You should experiment with these settings by incrementing their values and
+ observing the effect on your build times. You could experience a negative
+ impact to performance if you allocate too many resources to the DEX'ing process.
+</p>
+
+<h4 id="windows-defender">
+ Excluding your project from Windows Defender
+</h4>
+
+<p>
+ On Windows systems, Windows Defender may cause slowdowns while using Instant
+ Run. If you are using Windows Defender, you should <a class="external-link"
+ href=
+ "http://answers.microsoft.com/en-us/protect/wiki/protect_defender-protect_scanning/how-to-exclude-a-filefolder-from-windows-defender/f32ee18f-a012-4f02-8611-0737570e8eee">
+ exclude your Android Studio project folder from Windows Defender malware
+ scans</a>.
+</p>
+
+<h4 id="crashlytics">
+ Disabling Crashlytics for your debug build variant
+</h4>
+
+<p>
+ Using Crashlytics is known to cause slower build times. To improve build
+ performance while developing your app, you can <a class="external-link" href=
+ "https://docs.fabric.io/android/crashlytics/build-tools.html#disabling-crashlytics-for-debug-builds">
+ disable Crashlytics for your debug build variant</a>.
+</p>
+
+<h3 id="ir-limitations">
+ Limitations of Instant Run
+</h3>
+
+<p>
+ Instant Run is designed to speed up the build and deploy process in most
+ situations. However, there are some aspects to using Instant Run that might
+ affect its behavior and compatibility with your app. If you experience any
+ other issues while using Instant Run, please <a class="external-link" href=
+ "http://tools.android.com/filing-bugs">file a bug</a>.
+</p>
+
+<h4 id="multiple-devices">
+ Deploying to multiple devices
+</h4>
+
+<p>
+ Instant Run uses different techniques to perform hot, warm, and cold swaps
+ that are specific to the API level of the target device. For this reason,
+ while deploying an app to multiple devices at once, Android Studio
+ temporarily turns off Instant Run.
+</p>
+
+<h4 id="ir-multidex">
+ Multidexing your app
+</h4>
+
+<p>
+ If your project is configured for <a href=
+ "{@docRoot}tools/building/multidex.html#mdex-pre-l">Legacy Multidex</a>—that
+ is, when <code>build.gradle</code> is configured with <code>multiDexEnabled
+ true</code> and <code>minSdkVersion 20</code> or lower—and you deploy to
+ target devices running Android 4.4 (API level 20) or lower, Android Studio
+ disables Instant Run.
+</p>
+
+<p>
+ If <code>minSdkVersion</code> is set to 21 or higher, Instant Run
+ automatically configures your app for multidex. Because Instant Run only
+ works with the debug version of your app, you may need to <a href=
+ "{@docRoot}tools/building/multidex.html#mdex-gradle">configure your app for
+ multidex</a> when deploying your release build variant.
+</p>
+
+<h4 id="instrumented-tests">
+ Running instrumented tests and performance profilers
+</h4>
+
+<p>
+ Instrumented tests load both the debug APK and a test APK into the same
+ process on a test device, allowing control methods to override the normal
+ lifecycle of the app and perform tests. While running or debugging
+ instrumented tests, Android Studio does not inject the additional methods
+ required for Instant Run and turns the feature off.
+</p>
+
+<p>
+ While profiling an app, you should disable Instant Run. There is a small
+ performance impact when using Instant Run and a slightly larger impact when
+ overriding methods with a hot swap. This performance impact could interfere
+ with information provided by performance profiling tools. Additionally, the
+ stub methods generated with each hot swap can complicate stack traces.
+</p>
+
+<h4 id="plugins">
+ Using third-party plugins
+</h4>
+
+<p>
+ Android Studio temporarily disables the Java Code Coverage Library (JaCoCo)
+ and ProGuard while using Instant Run. Because Instant Run only works with
+ debug builds, this does not affect your release build.
+</p>
+
+<p>
+ Certain third-party plugins that perform bytecode enhancement may cause
+ issues with how Instant Run instruments your app. If you experience these
+ issues, but want to continue using Instant Run, you should disable those
+ plugins for your debug build variant. You can also help improve compatibility
+ with third-party plugins by <a class="external-link" href=
+ "http://tools.android.com/filing-bugs">filing a bug</a>.
+</p>
+
+<h4 id="multi-process-apps">
+ Pushing changes to multi-process apps
+</h4>
+
+<p>
+ Instant Run only instruments your app's main process in order to perform hot
+ swaps and warm swaps. When pushing code changes to other app processes, such
+ as changes to a method implementation or an existing resource, Instant Run
+ performs a <a href="#cold-swap">cold swap</a>.
+</p>
+
+<h4 id="disable-ir">
+ Disabling Instant Run
+</h4>
+
+<p>
+ To disable Instant Run:
+</p>
+
+<ol>
+ <li>Open the <strong>Settings</strong> or <strong>Preferences</strong>
+ dialog.
+ </li>
+
+ <li>Navigate to <strong>Build, Execution, Deployment</strong> >
+ <strong>Instant Run</strong>.
+ </li>
+
+ <li>Uncheck the box next to <strong>Enable Instant Run</strong>.
+ </li>
+</ol>
\ No newline at end of file
diff --git a/docs/html/tools/building/multidex.jd b/docs/html/tools/building/multidex.jd
index e441a7c63..7d05fb9 100644
--- a/docs/html/tools/building/multidex.jd
+++ b/docs/html/tools/building/multidex.jd
@@ -1,4 +1,4 @@
-page.title=Building Apps with Over 65K Methods
+page.title=Building Apps with Over 64K Methods
page.tags="65536","references","max","65k","dex","64k","multidex","multi-dex","methods"</p>
@jd:body
@@ -8,14 +8,14 @@
<h2>In this document</h2>
<ol>
<li><a href="#about">
- About the 65K Reference Limit</a>
+ About the 64K Reference Limit</a>
<ol>
<li><a href="#mdex-pre-l">Multidex support prior to Android 5.0</a></li>
<li><a href="#mdex-on-l">Multidex support for Android 5.0 and higher</a></li>
</ol>
</li>
<li><a href="#avoid">
- Avoiding the 65K Limit</a></li>
+ Avoiding the 64K Limit</a></li>
<li><a href="#mdex-gradle">
Configuring Your App for Multidex with Gradle</a>
<ol>
@@ -82,45 +82,71 @@
</p>
-<h2 id="about">About the 65K Reference Limit</h2>
+<h2 id="about">About the 64K Reference Limit</h2>
<p>
- Android application (APK) files contain executable bytecode files in the form of <a href=
- "https://source.android.com/devices/tech/dalvik/">Dalvik</a> Executable (DEX) files, which
- contain the compiled code used to run your app. The Dalvik Executable specification limits the
- total number of methods that can be referenced within a single DEX file to 65,536, including
- Android framework methods, library methods, and methods in your own code. Getting past this limit
- requires that you configure your app build process to generate more than one DEX file, known as a
- <em>multidex</em> configuration.
+ Android application (APK) files contain executable bytecode files in the form
+ of <a href="https://source.android.com/devices/tech/dalvik/">Dalvik</a>
+ Executable (DEX) files, which contain the compiled code used to run your app.
+ The Dalvik Executable specification limits the total number of methods that
+ can be referenced within a single DEX file to 65,536—including Android
+ framework methods, library methods, and methods in your own code. In the
+ context of computer science, the term <a class="external-link" href=
+ "https://en.wikipedia.org/wiki/Kilo-"><em>Kilo, K</em></a>, denotes 1024 (or
+ 2^10). Because 65,536 is equal to 64 X 1024, this limit is referred to as the
+ '64K reference limit'.
</p>
+<p>
+ Getting past this limit requires that you configure your app build process to
+ generate more than one DEX file, known as a <em>multidex</em> configuration.
+</p>
<h3 id="mdex-pre-l">Multidex support prior to Android 5.0</h3>
<p>
- Versions of the platform prior to Android 5.0 use the Dalvik runtime for executing app code. By
- default, Dalvik limits apps to a single classes.dex bytecode file per APK. In order to get around
- this limitation, you can use the <a href="{@docRoot}tools/support-library/features.html#multidex">
- multidex support library</a>, which becomes part of the primary DEX file of your app and then
+ Versions of the platform prior to Android 5.0 (API level 21) use the Dalvik
+ runtime for executing app code. By default, Dalvik limits apps to a single
+ classes.dex bytecode file per APK. In order to get around this limitation,
+ you can use the <a href=
+ "{@docRoot}tools/support-library/features.html#multidex">multidex support
+ library</a>, which becomes part of the primary DEX file of your app and then
manages access to the additional DEX files and the code they contain.
</p>
+<p class="note">
+ <strong>Note:</strong> If your project is configured for multidex with
+ <code>minSdkVersion 20</code> or lower, and you deploy to target devices
+ running Android 4.4 (API level 20) or lower, Android Studio disables <a href=
+ "{@docRoot}tools/building/building-studio.html#instant-run">Instant Run</a>.
+</p>
<h3 id="mdex-on-l">Multidex support for Android 5.0 and higher</h3>
<p>
- Android 5.0 and higher uses a runtime called ART which natively supports loading multiple dex
- files from application APK files. ART performs pre-compilation at application install time which
- scans for classes(..N).dex files and compiles them into a single .oat file for execution by the
- Android device. For more information on the Android 5.0 runtime, see <a href=
- "https://source.android.com/devices/tech/dalvik/art.html">Introducing ART</a>.
+ Android 5.0 (API level 21) and higher uses a runtime called ART which
+ natively supports loading multiple dex files from application APK files. ART
+ performs pre-compilation at application install time which scans for
+ classes(..N).dex files and compiles them into a single .oat file for
+ execution by the Android device. For more information on the Android 5.0
+ runtime, see <a href=
+ "https://source.android.com/devices/tech/dalvik/art.html">Introducing
+ ART</a>.
</p>
+<p class="note">
+ <strong>Note:</strong> While using <a href=
+ "{@docRoot}tools/building/building-studio.html#instant-run">Instant Run</a>,
+ Android Studio automatically configures your app for multidex when your app's
+ <code>minSdkVersion</code> is set to 21 or higher. Because Instant Run only
+ works with the debug version of your app, you still need to configure your
+ release build for multidex to avoid the 64K limit.
+</p>
-<h2 id="avoid">Avoiding the 65K Limit</h2>
+<h2 id="avoid">Avoiding the 64K Limit</h2>
<p>
- Before configuring your app to enable use of 65K or more method references, you should take steps
+ Before configuring your app to enable use of 64K or more method references, you should take steps
to reduce the total number of references called by your app code, including methods defined by
your app code or included libraries. The following strategies can help you avoid hitting the dex
reference limit:
@@ -173,8 +199,9 @@
</ul>
<p>
- Modify your app Gradle build file configuration to include the support library and enable
- multidex output, as shown in the following Gradle build file snippet:
+ Modify the module-level <code>build.gradle</code> file configuration to
+ include the support library and enable multidex output, as shown in the
+ following code snippet:
</p>
<pre>
@@ -199,13 +226,6 @@
}
</pre>
-<p class="note">
- <strong>Note:</strong> You can specify the <code>multiDexEnabled</code> setting in the
- <code>defaultConfig,</code> <code>buildType</code>, or <code>productFlavor</code> sections of
- your Gradle build file.
-</p>
-
-
<p>
In your manifest add the {@link android.support.multidex.MultiDexApplication} class from the
multidex support library to the application element.
@@ -444,7 +464,7 @@
dependencies {
androidTestCompile('com.android.support:multidex-instrumentation:1.0.1') {
exclude group: 'com.android.support', module: 'multidex'
- }
+ }
}
</pre>
</p>
diff --git a/docs/html/tools/devices/emulator.jd b/docs/html/tools/devices/emulator.jd
index 1e70562..d9a38f7 100644
--- a/docs/html/tools/devices/emulator.jd
+++ b/docs/html/tools/devices/emulator.jd
@@ -1,4 +1,7 @@
-page.title=Using the Emulator
+page.title=Running Apps in the Android Emulator
+parent.title=Android Studio
+parent.link=index.html
+page.tags=emulator
@jd:body
<div id="qv-wrapper">
@@ -6,1568 +9,650 @@
<h2>In this document</h2>
<ol>
- <li><a href="#overview">Overview</a></li>
- <li><a href="#avds">Android Virtual Devices and the Emulator</a></li>
- <li><a href="#starting">Starting and Stopping the Emulator</a></li>
- <li><a href="#apps">Installing Applications on the Emulator</a></li>
- <li><a href="#acceleration">Using Hardware Acceleration</a>
- <ol>
- <li><a href="#accel-graphics">Configuring Graphics Acceleration</a></li>
- <li><a href="#accel-vm">Configuring Virtual Machine Acceleration</a></li>
- </ol>
- </li>
- <li><a href="#sdcard">SD Card Emulation</a>
- <ol>
- <li><a href="#sdcard-creating">Creating an SD card image</a></li>
- <li><a href="#sdcard-files">Copying files to an SD card image</a></li>
- <li><a href="#sdcard-loading">Loading an SD card image</a></li>
- </ol>
- </li>
- <li><a href="#diskimages">Working with Emulator Disk Images</a>
- <ol>
- <li><a href="#defaultimages">Default image files</a></li>
- <li><a href="#runtimeimages">Runtime images: user data and SD card</a></li>
- <li><a href="#temporaryimages">Temporary images</a></li>
- </ol>
- </li>
- <li><a href="#emulatornetworking">Emulator Networking</a>
- <ol>
- <li><a href="#networkaddresses">Network Address Space</a></li>
- <li><a href="#networkinglimitations">Local Networking Limitations</a></li>
- <li><a href="#redirection">Using Network Redirection</a></li>
- <li><a href="#dns">Configuring the Emulator's DNS Settings</a></li>
- <li><a href="#proxy">Using the Emulator with a Proxy</a></li>
- <li><a href="#connecting">Interconnecting Emulator Instances</a></li>
- <li><a href="#calling">Sending a Voice Call or SMS to Another Emulator Instance</a></li>
- </ol>
- </li>
- <li><a href="#console">Using the Emulator Console</a>
- <ol>
- <li><a href="#portredirection">Port Redirection</a></li>
- <li><a href="#geo">Geo Location Provider Emulation</a></li>
- <li><a href="#events">Hardware Events Emulation</a></li>
- <li><a href="#power">Device Power Characteristics</a></li>
- <li><a href="#netstatus">Network Status</a></li>
- <li><a href="#netdelay">Network Delay Emulation</a></li>
- <li><a href="#netspeed">Network Speed Emulation</a></li>
- <li><a href="#telephony">Telephony Emulation</a></li>
- <li><a href="#sms">SMS Emulation</a></li>
- <li><a href="#vm">VM State</a></li>
- <li><a href="#window">Emulator Window</a></li>
- <li><a href="#terminating">Terminating an Emulator Instance</a></li>
- </ol>
- </li>
- <li><a href="#limitations">Emulator Limitations</a></li>
- <li><a href="#troubleshooting">Troubleshooting Emulator Problems</a></li>
+ <li><a href="#about">About the Android Emulator</a></li>
+ <li><a href="#runningapp">Running an App in the Android Emulator</a></li>
+ <li><a href="#runningemulator">Launching the Android Emulator Without Running an App</a></li>
+ <li><a href="#navigate">Navigating on the Screen</a></li>
+ <li><a href="#tasks">Performing Basic Tasks in the Emulator</a></li>
+ <li><a href="#extended">Working With Extended Controls, Settings, and Help</a></li>
+
</ol>
<h2>See also</h2>
<ol>
- <li><a href="{@docRoot}tools/help/emulator.html">Android Emulator</a></li>
- <li><a href="{@docRoot}tools/devices/managing-avds.html">Managing AVDs with AVD Manager</a></li>
+ <li><a href="{@docRoot}tools/help/emulator.html">Android Emulator Command Line Features</a></li>
+ <li><a href="{@docRoot}tools/devices/managing-avds.html">Managing AVDs with
+ AVD Manager</a></li>
</ol>
+
</div>
</div>
-<p>The Android SDK includes a virtual mobile device emulator
-that runs on your computer. The emulator lets you prototype, develop and test
-Android applications without using a physical device. </p>
+<p>The Android Emulator simulates a device and displays it on your development
+computer. It lets you prototype, develop, and test
+Android apps without using a hardware device. The emulator supports Android
+phone, tablet, Android Wear, and Android TV devices. It comes with predefined
+device types
+so you can get started quickly, and you can create your own device definitions
+and emulator skins.</p>
-<p>The Android emulator mimics all of the hardware and software features
-of a typical mobile device, except that it cannot place actual phone
-calls. It provides a variety of navigation and control keys, which you can "press"
-using your mouse or keyboard to generate events for your application. It also
-provides a screen in which your application is displayed, together with any other
-active Android applications. </p>
+<p>The Android Emulator is fast,
+powerful, and feature-rich. It can transfer information faster than using
+a connected hardware device, speeding up the development process. The
+multi-core feature lets the emulator take advantage of multiple core
+processors on your development computer to improve emulator performance even
+more.</p>
-<img src="{@docRoot}images/emulator@2x.png"
-srcset="{@docRoot}images/emulator.png 1x, {@docRoot}images/emulator@2x.png 2x" alt=""
- width="367" height="330"/>
+<img src="{@docRoot}images/tools/e-emulator.png" style="height:400px" alt="emulator"/>
-<p>To let you model and test your application more easily, the emulator utilizes
-Android Virtual Device (AVD) configurations. AVDs let you define certain hardware
-aspects of your emulated phone and allow you to create many configurations to test
-many Android platforms and hardware permutations. Once your application is running on
+<h2 id="about">About the Android Emulator</h2>
+
+<p>You can launch an app on the emulator when you run your project, or you can
+drag an APK file onto the emulator to install it. As with a hardware device,
+after you install an app
+on a virual device, it remains until you uninstall or replace it. If needed, you
+can test how multiple apps, such as your own or system apps, work with each
+other.</p>
+
+<h3 id="features">Features for trying out your apps</h3>
+
+<p>You interact with the emulator just as you would with a hardware device, but
+using your mouse and keyboard, and emulator buttons and controls.
+The emulator supports virtual hardware buttons and touchscreens, including
+two-finger operations,
+as well as directional pads (D-pads), trackballs, wheels, and various
+sensors. You can dynamically resize the emulator window as needed, zoom in and
+out, change the orientation, and even take a screenshot.</p>
+
+<p>When your app is running on
the emulator, it can use the services of the Android platform to invoke other
-applications, access the network, play audio and video, store and retrieve data,
-notify the user, and render graphical transitions and themes. </p>
+apps, access the network, play audio and video, accept audio input,
+store and retrieve data, notify the user, and render graphical transitions and
+themes. The emulator has controls that let
+you easily send incoming phone calls and text messages, specify
+the location of the device, simulate fingerprint scans, specify network
+speed and status, and simulate battery properties. The emulator can
+simulate an SD card and internal data storage; you can drag a file, such as a
+graphics or data file, onto the emulator to store it.</p>
-<p>The emulator also includes a variety of debug capabilities, such as a console
-from which you can log kernel output, simulate application interrupts (such as
-arriving SMS messages or phone calls), and simulate latency effects and dropouts
-on the data network.</p>
+<h3 id="avds">Android Virtual Device configurations</h3>
-
-
-<h2 id="overview">Overview</h2>
-
-<p>The Android emulator is an application that provides a virtual
-mobile device on which you can run your Android applications. It runs a full
-Android system stack, down to the kernel level, that includes a set of
-preinstalled applications (such as the dialer) that you can access from your
-applications. You can choose what version of the Android system you want to
-run in the emulator by configuring AVDs, and you can also customize the
-mobile device skin and key mappings. When launching the emulator and at runtime,
-you can use a variety of commands and options to control its behavior.
-</p>
-
-<p>The Android system images available through the Android SDK Manager contain
-code for the Android Linux kernel, the native libraries, the Dalvik VM, and the
-various Android packages (such as the Android framework and preinstalled
-applications). The emulator provides dynamic binary translation of device
-machine code to the OS and processor architecture of your development
-machine.</p>
-
-<p>The Android emulator supports many hardware features likely to be found on
-mobile devices, including: </p>
-
-<ul>
- <li>An ARMv5, ARMv7, or x86 CPU</li>
- <li>A 16-bit LCD display</li>
- <li>One or more keyboards (a Qwerty-based keyboard and associated Dpad/Phone
-buttons)</li>
- <li>A sound chip with output and input capabilities</li>
- <li>Flash memory partitions (emulated through disk image files on the
-development machine)</li>
- <li>A GSM modem, including a simulated SIM Card</li>
- <li>A camera, using a webcam connected to your development computer.</li>
- <li>Sensors like an accelerometer, using data from a USB-connected Android device.</li>
-</ul>
-
-<p>The following sections describe the emulator and its use for development of Android
-applications in more detail.</p>
-
-
-<h2 id="avds">Android Virtual Devices and the Emulator</h2>
-
-<p>To use the emulator, you first must create one or more AVD configurations. In each
-configuration, you specify an Android platform to run in the emulator and the set of hardware
-options and emulator skin you want to use. Then, when you launch the emulator, you specify
-the AVD configuration that you want to load. </p>
+<p>The emulator uses an Android Virtual Device (AVD) configuration to determine
+the look, functionality, and system image of the simulated device. AVDs let you
+define certain hardware aspects of your emulated devices and allow you to create
+many configurations to test different Android platforms and hardware
+permutations.</p>
<p>Each AVD functions as an independent device, with its own private storage for
-user data, SD card, and so on. When you launch the emulator with an AVD configuration,
-it automatically loads the user data and SD card data from the AVD directory. By default,
-the emulator stores the user data, SD card data, and cache in the AVD directory.</p>
+user data, SD card, and so on. When you launch the emulator with an AVD
+configuration, it automatically loads the user data and SD card data from the
+AVD directory. By default, the emulator stores the user data, SD card data, and
+cache in the AVD directory.</p>
-<p>To create and manage AVDs you use the AVD Manager UI or the <code>android</code> tool
-that is included in the SDK.
-For complete information about how to set up AVDs, see <a
-href="{@docRoot}tools/devices/index.html">Managing Virtual Devices</a>.</p>
+<p>To create and manage AVDs, use the
+<a href="{@docRoot}tools/devices/managing-avds.html">AVD Manager</a>.
+For more information, see
+<a href="{@docRoot}tools/devices/index.html">Managing Virtual Devices</a>.</p>
+<h3 id="manifest">Manifest settings</h3>
-<h2 id="starting">Starting and Stopping the Emulator</h2>
+<p>For your app to use certain emulator device features, you need to specify
+in the manifest that your app will use them. For example, an Android Wear watch
+requires the following <code><uses-feature></code> setting:</p>
-<p>During development and testing of your application, you install and run your
-application in the Android emulator. You can launch the emulator as a standalone
-application from a command line, or you can run it from within your Android Studio
-development environment. In either case, you specify the AVD configuration to
-load and any startup options you want to use, as described in this document.
-</p>
-
-<p>You can run your application on a single instance of the emulator or,
-depending on your needs, you can start multiple emulator instances and run your
-application in more than one emulated device. You can use the emulator's
-built-in commands to simulate GSM phone calling or SMS between emulator
-instances, and you can set up network redirection that allows emulators to send
-data to one another. For more information, see <a href="#telephony">Telephony
-Emulation</a>, <a href="#sms">SMS Emulation</a>, and
-<a href="#emulatornetworking">Emulator Networking</a></p>
-
-<p>To start an instance of the emulator from the command line, navigate to the
-<code>tools/</code> folder of the SDK. Enter <code>emulator</code> command
-like this: </p>
-
-<pre>emulator -avd <avd_name> [<options>]</pre>
-
-<p>This initializes the emulator, loads an AVD configuration and displays the emulator
-window. For more information about command line options for the emulator, see the
-<a href="{@docRoot}tools/help/emulator.html">Android Emulator</a> tool reference.</p>
-
-<p class="note"><strong>Note:</strong> You can run multiple
-instances of the emulator concurrently, each with its own AVD configuration and
-storage area for user data, SD card, and so on.</p>
-
-<p>When you run your app from Android Studio, it installs and launches the
-app on your connected device or emulator (launching the emulator, if necessary).
-You can specify emulator startup options in the Run/Debug
-dialog, in the Target tab. When the emulator is running, you can issue
-console commands as described later in this document.</p>
-
-<p>If you are not working in Android Studio, see <a href="#apps">Installing Applications
-on the Emulator</a> for information about how to install your application.</p>
-
-<p>To stop an emulator instance, just close the emulator's window.</p>
-
-<p>For a reference of the emulator's startup commands and keyboard mapping, see
-the <a href="{@docRoot}tools/help/emulator.html">Android Emulator</a> tool
-reference.</p>
-
-
-<h2 id="apps">Installing Applications on the Emulator</h2>
-
-<p>If you don't have access to Android Studio, you can install your application on the
-emulator using the <a href="{@docRoot}tools/help/adb.html#move">adb</a> utility. Before
-installing the application, you need to build and package it into an <code>.apk</code> as described
-in <a href="{@docRoot}tools/building/index.html">Building and
-Running Apps</a>. Once the application is installed, you can start the emulator from the command
-line as described previously, using any startup options necessary.
-When the emulator is running, you can also connect to the emulator instance's
-<a href="#console">console</a> to issue commands as needed.</p>
-
-<p>As you update your code, you periodically package and install it on the emulator.
-The emulator preserves the application and its state data across restarts,
-in a user-data disk partition. To ensure that the application runs properly
-as you update it, you may need to delete the emulator's user-data partition.
-To do so, start the emulator with the <code>-wipe-data</code> option.
-For more information about the user-data partition and other emulator storage,
-see <a href="#diskimages">Working with Emulator Disk Images</a>.</p>
-
-
-<h2 id="acceleration">Using Hardware Acceleration</h2>
-
-<p>In order to make the Android emulator run faster and be more responsive, you can configure it to
-take advantage of hardware acceleration, using a combination of configuration options, specific
-Android system images and hardware drivers.</p>
-
-
-<h3 id="accel-graphics">Configuring Graphics Acceleration</h3>
-
-<p class="caution"><strong>Caution:</strong> As of SDK Tools Revision 17, the graphics
-acceleration feature for the emulator is experimental; be alert for incompatibilities and
-errors when using this feature. </p>
-
-<p>Graphics acceleration for the emulator takes advantage of your development computer's graphics
-hardware, specifically its graphics processing unit (GPU), to make screen drawing faster. To use
-the graphics acceleration feature, you must have the following versions of the Android development
-tools installed:</p>
-
-<ul>
- <li>Android SDK Tools, Revision 17 or higher</li>
- <li>Android SDK Platform API 15, Revision 3 or higher</li>
-</ul>
-
-<p>Use the <a href="{@docRoot}sdk/installing/index.html#AddingComponents">Android SDK
-Manager</a> to install these components:</p>
-
-<p class="note"><strong>Note:</strong> Not all applications are compatible with graphics hardware
-acceleration. In particular, the Browser application and applications using the {@link
-android.webkit.WebView} component are not compatible with graphics acceleration.</p>
-
-<p>To configure an AVD to use graphics acceleration:</p>
-
-<ol>
- <li>Make sure you have the required SDK components installed (listed above).</li>
- <li>Start the AVD Manager and create a new AVD with the <strong>Target</strong> value of
-<strong>Android 4.0.3 (API Level 15)</strong>, revision 3 or higher.</li>
- <li>If you want to have graphics acceleration enabled by default for this AVD, in the
-<strong>Hardware</strong> section, click <strong>New</strong>, select <strong>GPU emulation</strong>
-and set the value to <strong>Yes</strong>.
- <p class="note"><strong>Note:</strong> You can also enable graphics acceleration when you
-start an emulator using command line options as describe in the next section.</p>
- </li>
- <li>Name the AVD instance and select any other configuration options.
- <p class="caution"><strong>Caution:</strong> Do not select the <strong>Snapshot: Enabled</strong>
-option. Snapshots are not supported for emulators with graphics acceleration enabled.</p>
- </li>
- <li>Click <strong>Create AVD</strong> to save the emulator configuration.</li>
-</ol>
-
-<p>If you set <strong>GPU emulation</strong> to <strong>Yes</strong> for your AVD, then graphics
-acceleration is automatically enabled when you run it. If you did not enable <strong>GPU
-emulation</strong> when you created the AVD, you can still enable it at runtime.</p>
-
-<p>To enable graphics acceleration at runtime for an AVD:</p>
-
-<ul>
- <li>If you are running the emulator from the command line, just include the {@code -gpu on}
-option:
-<pre>emulator -avd <avd_name> -gpu on</pre>
- <p class="note"><strong>Note:</strong> You must specify an AVD configuration that uses
-Android 4.0.3 (API Level 15, revision 3) or higher system image target. Graphics acceleration is not
-available for earlier system images.</p>
- </li>
- <li>If you are running the emulator from Android Studio, run your Android application using an AVD
-with the {@code -gpu on} option enabled:
- <ol>
- <li>In Android Studio, click your Android application module folder and then select
- <strong>Run > Edit Configurations...</strong></li>
- <li>In the left panel of the <strong>Run/Debug Configurations</strong> dialog, select your Android
- run configuration or create a new configuration.</li>
- <li>Under the <strong>Target Device </strong> options,
- select the AVD you created in the previous procedure.</li>
- <li>In the <strong>Emulator</strong> tab, in the
- <strong>Additional command line options</strong> field, enter:<br>
- {@code -gpu on}</li>
- <li>Run your Android project using this run configuration.</li>
- </ol>
- </li>
-</ul>
-
-
-<h3 id="accel-vm">Configuring Virtual Machine Acceleration</h2>
-
-<p class="caution"><strong>Caution:</strong> As of SDK Tools Revision 17, the virtual machine
-acceleration feature for the emulator is experimental; be alert for incompatibilities and errors
-when using this feature.</p>
-
-<p>Many modern CPUs provide extensions for running virtual machines (VMs) more efficiently. Taking
-advantage of these extensions with the Android emulator requires some additional configuration of
-your development system, but can significantly improve the execution speed. Before attempting to use
-this type of acceleration, you should first determine if your development system’s CPU supports one
-of the following virtualization extensions technologies:</p>
-
-<ul>
- <li>Intel Virtualization Technology (VT, VT-x, vmx) extensions</li>
- <li>AMD Virtualization (AMD-V, SVM) extensions (only supported for Linux)</li>
-</ul>
-
-<p>The specifications from the manufacturer of your CPU should indicate if it supports
-virtualization extensions. If your CPU does not support one of these virtualization technologies,
-then you cannot use virtual machine acceleration.</p>
-
-<p class="note"><strong>Note:</strong> Virtualization extensions are typically enabled through
-your computer's BIOS and are frequently turned off by default. Check the documentation for your
-system's motherboard to find out how to enable virtualization extensions.</p>
-
-<p>Once you have determined that your CPU supports virtualization extensions, make sure you can work
-within these additional requirements of running an emulator inside an accelerated virtual
-machine:</p>
-
-<ul>
- <li><strong>x86 AVD Only</strong> - You must use an AVD that is uses an x86 system image target.
-AVDs that use ARM-based system images cannot be accelerated using the emulator configurations
-described here.</li>
- <li><strong>Not Inside a VM</strong> - You cannot run a VM-accelerated emulator inside another
-virtual machine, such as a VirtualBox or VMWare-hosted virtual machine. You must run the emulator
-directly on your system hardware.</li>
- <li><strong>Other VM Drivers</strong> - If you are running another virtualization technology on
-your system such as VirtualBox or VMWare, you may need to unload the driver for that virtual machine
-hosting software before running an accelerated emulator.</li>
- <li><strong>OpenGL® Graphics</strong> - Emulation of OpenGL ES graphics may not perform at the
-same level as an actual device.</li>
-</ul>
-
-<p>To use virtual machine acceleration with the emulator, you need the following version of Android
-development tools. Use the <a href="{@docRoot}sdk/installing/index.html#AddingComponents">Android SDK
-Manager</a> to install these components:</p>
-
-<ul>
- <li>Android SDK Tools, Revision 17 or higher</li>
- <li>Android x86-based system image</li>
-</ul>
-
-<p>If your development environment meets all of the requirements for running a VM-accelerated
-emulator, you can use the AVD Manager to create an x86-based AVD configuration:</p>
-
-<ol>
- <li>In the Android SDK Manager, make sure you have an x86-based <strong>System Image</strong>
- installed for your target Android version. If you do not have an x86 <strong>System
- Image</strong> installed, select one in the Android SDK Manager and install it.
- <p class="note"><strong>Tip:</strong> System images are listed under each API Level in the SDK
- Manager. An x86 system image may not be available for all API levels.</p>
- </li>
- <li>Start the AVD Manager and create a new AVD with an x86 value for the
-<strong>CPU/ABI</strong> field. You may need to select a specific <strong>Target</strong> value, or
-select a <strong>Target</strong> value and then select a specific <strong>CPU/ABI</strong>
-option.</li>
- <li>Name the emulator instance and select any other configuration options.</li>
- <li>Click <strong>Create AVD</strong> to save the emulator configuration.</li>
-</ol>
-
-<h4 id="vm-windows">Configuring VM Acceleration on Windows</h4>
-
-<p>Virtual machine acceleration for Windows requires the installation of the Intel Hardware
-Accelerated Execution Manager (Intel HAXM). The software requires an Intel CPU with
-Virtualization Technology (VT) support and one of the following operating systems:</p>
-
-<ul>
- <li>Windows 7 (32/64-bit)</li>
- <li>Windows Vista (32/64-bit)</li>
- <li>Windows XP (32-bit only)</li>
-</ul>
-
-<p>To install the virtualization driver:</p>
-
-<ol>
- <li>Start the Android SDK Manager, select <strong>Extras</strong> and then select <strong>Intel
-Hardware Accelerated Execution Manager</strong>.</li>
- <li>After the download completes, execute {@code
-<sdk>/extras/intel/Hardware_Accelerated_Execution_Manager/IntelHAXM.exe}.</li>
- <li>Follow the on-screen instructions to complete installation.</li>
- <li>After installation completes, confirm that the virtualization driver is operating correctly by
-opening a command prompt window and running the following command:
- <pre>sc query intelhaxm</pre>
- <p>You should see a status message including the following information:</p>
<pre>
-SERVICE_NAME: intelhaxm
- ...
- STATE : 4 RUNNING
- ...
-</pre>
- </li>
-</ol>
-
-<p>To run an x86-based emulator with VM acceleration:</p>
-<ul>
- <li>If you are running the emulator from the command line, just specify an x86-based AVD:
-<pre>emulator -avd <avd_name></pre>
- <p class="note"><strong>Note:</strong> You must provide an x86-based AVD configuration
-name, otherwise VM acceleration will not be enabled.</p>
- </li>
- <li>If you are running the emulator from Android Studio, run your Android application with an x86-based
-AVD:
- <ol>
- <li>In Android Studio, click your Android project folder and then select <strong>Run > Edit
-Configurations...</strong></li>
- <li>In the left panel of the <strong>Run/Debug Configurations</strong> dialog, select your Android
-run configuration or create a new configuration.</li>
- <li>Under the <strong>Target Device</strong> options, select the x86-based AVD you created
-previously.</li>
- <li>Run your Android project using this run configuration.</li>
- </ol>
- </li>
-</ul>
-
-<p>You can adjust the amount of memory available to the Intel HAXM kernel extension by re-running
-its installer.</p>
-
-<p>You can stop using the virtualization driver by uninstalling it. Re-run the installer or use
-the Control Panel to remove the software.</p>
-
-
-<h4 id="vm-mac">Configuring VM Acceleration on Mac</h4>
-
-<p>Virtual machine acceleration on a Mac requires the installation of the Intel Hardware Accelerated
-Execution Manager (Intel HAXM) kernel extension to allow the Android emulator to make use of CPU
-virtualization extensions. The kernel extension is compatible with Mac OS X Snow Leopard (version
-10.6.0) and higher.</p>
-
-<p>To install the Intel HAXM kernel extension:</p>
-
-<ol>
- <li>Start the Android SDK Manager, select <strong>Extras</strong> and then select <strong>Intel
-Hardware Accelerated Execution Manager</strong>.
- <li>After the download completes, execute
- {@code <sdk>/extras/intel/Hardware_Accelerated_Execution_Manager/IntelHAXM.dmg}.</li>
- <li>Double click the <strong>IntelHAXM.mpkg</strong> icon to begin installation.</li>
- <li>Follow the on-screen instructions to complete installation.</li>
- <li>After installation completes, confirm that the new kernel extension is operating correctly by
-opening a terminal window and running the following command:
- <pre>kextstat | grep intel</pre>
- <p>You should see a status message containing the following extension name, indicating that the
- kernel extension is loaded:</p>
- <pre>com.intel.kext.intelhaxm</pre>
- </li>
-</ol>
-
-<p>To run an x86-based emulator with VM acceleration:</p>
-<ul>
- <li>If you are running the emulator from the command line, just specify an x86-based AVD:
-<pre>emulator -avd <avd_name></pre>
- <p class="note"><strong>Note:</strong> You must provide an x86-based AVD configuration
-name, otherwise VM acceleration will not be enabled.</p>
- </li>
- <li>If you are running the emulator from Andriod Studio, run your Android application with an x86-based
-AVD:
- <ol>
- <li>In Android Studio, click your Android module folder and then select <strong>Run > Edit
-Configurations...</strong></li>
- <li>In the left panel of the <strong>Run/Debug Configurations</strong> dialog, select your Android
-run configuration or create a new configuration.</li>
- <li>Under the <strong>Target Device</strong> options,
- select the x86-based AVD you created previously.</li>
- <li>Run your Android project using this run configuration.</li>
- </ol>
- </li>
-</ul>
-
-<p>You can adjust the amount of memory available to the Intel HAXM kernel extension by re-running
-the installer.</p>
-
-<p>You can stop using the virtualization kernel driver by uninstalling it. Before removing it, shut
-down any running x86 emulators. To unload the virtualization kernel driver, run the following
-command in a terminal window:</p>
-
-<pre>sudo /System/Library/Extensions/intelhaxm.kext/Contents/Resources/uninstall.sh</pre>
-
-<h4 id="vm-linux">Configuring VM Acceleration on Linux</h4>
-
-<p>Linux-based systems support virtual machine acceleration through the KVM software package. Follow
-<a href="https://www.google.com/?q=kvm+installation">instructions for installing KVM</a> on your
-Linux system, and verify that KVM is enabled. In addition to following the installation
-instructions, be aware of these configuration requirements:</p>
-
-<ul>
- <li>Running KVM requires specific user permissions, make sure you have sufficient permissions
-according to the KVM installation instructions.</li>
- <li>If you use another virtualization technology in your Linux platform, unload its kernel driver
-before running the x86 emulator. For example, the VirtualBox driver program is {@code vboxdrv}.</li>
-</ul>
-
-<p>To run an x86-based emulator with VM acceleration:</p>
-
-<ul>
- <li>If you are running the emulator from the command line, start the emulator with an x86-based
-AVD and include the KVM options:
-<pre>emulator -avd <avd_name> -qemu -m 512 -enable-kvm</pre>
- <p class="note"><strong>Note:</strong> You must provide an x86-based AVD configuration
-name, otherwise VM acceleration will not be enabled.</p>
- </li>
- <li>If you are running the emulator from Android Studio, run your Android application with an
- x86-based AVD and include the KVM options:
- <ol>
- <li>In Android Studio, click your Android module folder and then select <strong>Run > Edit
-Configurations...</strong></li>
- <li>In the left panel of the <strong>Run/Debug Configurations</strong> dialog, select your Android
-run configuration or create a new configuration.</li>
- <li>Under the <strong>Target Device</strong> options, select the x86-based AVD you created
-previously.</li>
- <li>In the <strong>Emulator</strong> tab, in the
- <strong>Additional command line options</strong> field, enter:
- <pre>-qemu -m 512 -enable-kvm</pre>
- </li>
- <li>Run your Android project using this run configuration.</li>
- </ol>
- </li>
-</ul>
-
-<p class="note"><strong>Important:</strong> When using the {@code -qemu} command line option, make sure
-it is the last parameter in your command. All subsequent options are interpreted as qemu-specific
-parameters.</p>
-
-
-<h2 id="sdcard">SD Card Emulation</h2>
-
-<p>You can create a disk image and then load it to the emulator at startup, to
-simulate the presence of a user's SD card in the device. To do this, you can specify
-an SD card image when you create an AVD, or you can use the mksdcard utility included
-in the SDK.</p>
-
-<p>The following sections describe how to create an SD card disk image, how to copy
-files to it, and how to load it in the emulator at startup. </p>
-
-<p>Note that you can only load a disk image at emulator startup. Similarly, you
-can not remove a simulated SD card from a running emulator. However, you can
-browse, send files to, and copy/remove files from a simulated SD card either
-with adb or the emulator. </p>
-
-<p>The emulator supports emulated SDHC cards, so you can create an SD card image
-of any size up to 128 gigabytes.</p>
-
-
-<h3 id="sdcard-creating">Creating an SD card image</h3>
-
-<p>There are several ways of creating an SD card image. The easiest way is to use the
-<strong>AVD Manager</strong> to create a new SD card by specifying a size when you create an AVD.
-You can also use the {@code android} command line tool when creating an AVD. Just add the
-<code>-c</code> option to your command: </p>
-
-<pre>android create avd -n <avd_name> -t <targetID> -c <size>[K|M]</pre>
-
-<p>The <code>-c</code> option can also be used to to specify a path to an SD card
-image for the new AVD. For more information, see <a
-href="{@docRoot}tools/devices/managing-avds-cmdline.html">Managing Virtual Devices
-from the Command Line</a>.
-</p>
-
-<p>You can also use the mksdcard tool, included in the SDK, to create a FAT32 disk
-image that you can load in the emulator at startup. You can access mksdcard in
-the tools/ directory of the SDK and create a disk image like this: </p>
-
-<pre>mksdcard <size> <file></pre>
-
-<p>For example:</p>
-
-<pre>mksdcard 1024M sdcard1.iso</pre>
-
-<p>For more information, see <a
-href="{@docRoot}tools/help/mksdcard.html"><code>mksdcard</code></a>.</p>
-
-
-<h3 id="sdcard-files">Copying files to an SD card image</h3>
-
-<p>Once you have created the disk image, you can copy files to it prior to
-loading it in the emulator. To copy files, you can mount the image as a loop
-device and then copy the files to it, or you can use a utility such as {@code mtools} to
-copy the files directly to the image. The {@code mtools} package is available for Linux,
-Mac, and Windows.</p>
-
-<p>Alternatively, you can use the {@code adb push} command to move files onto an SD card image
-while it is loaded in an emulator. For more information see the <a
-href="{@docRoot}tools/help/adb.html#copyfiles">{@code adb push}</a> documentation.</p>
-
-<h3 id="sdcard-loading">Loading an SD card image</h3>
-
-<p>By default, the emulator loads the SD card image that is stored with the active
-AVD (see the <code>-avd</code> startup option).</p>
-
-<p>Alternatively, you can start the emulator with the
-<code>-sdcard</code> flag and specify the name and path of your image (relative
-to the current working directory): </p>
-
-<pre>emulator -sdcard <filepath></pre>
-
-
-<h2 id="diskimages">Working with Emulator Disk Images</h2>
-
-<p>The emulator uses mountable disk images stored on your development machine to
-simulate flash (or similar) partitions on an actual device. For example, it uses a
-disk image containing an emulator-specific kernel, the Android system, a
-ramdisk image, and writeable images for user data and simulated SD card.</p>
-
-<p>To run properly, the emulator requires access to a specific set of disk image
-files. By default, the Emulator always looks for the disk images in the
-private storage area of the AVD in use. If no images exist there when
-the Emulator is launched, it creates the images in the AVD directory based on
-default versions stored in the SDK. </p>
-
-<p class="note"><strong>Note:</strong> The default storage location for
-AVDs is in <code>~/.android/avd</code> on OS X and Linux, <code>C:\Documents and
-Settings\<user>\.android\</code> on Windows XP, and
-<code>C:\Users\<user>\.android\</code>
-on Windows Vista.</p>
-
-<p>To let you use alternate or custom versions of the image files, the emulator
-provides startup options that override the default locations and filenames of
-the image files. When you use one of these options, the emulator searches for the image
-file under the image name or location that you specify; if it can not locate the
-image, it reverts to using the default names and location.</p>
-
-<p>The emulator uses three types of image files: default image files, runtime
-image files, and temporary image files. The sections below describe how to
-override the location/name of each type of file. </p>
-
-<h3 id="defaultimages">Default image files</h3>
-
-<p>When the emulator launches, but does not find an existing user data image in
-the active AVD's storage area, it creates a new one from a default version
-included in the SDK. The default user data image is read-only. The image
-files are read-only.</p>
-
-<p>The emulator provides the <code>-system <dir></code> startup option to
-let you override the location where the emulator looks for the default
-user data image. </p>
-
-<p>The emulator also provides a startup option that lets you override the name
-of the default user data image, as described in the following table. When you use the
-option, the emulator looks in the default directory, or in a custom location
-(if you specified <code>-system <dir></code>). </p>
-
-
-<table>
-<tr>
- <th width="10%" >Name</th>
- <th width="30%" >Description</th>
- <th width="40%" >Comments</th>
-</tr>
-
-<!--
-<tr>
- <td><code>kernel-qemu.img</code></td>
- <td>The emulator-specific Linux kernel image</td>
- <td>Override using <code>-kernel <file></code></td>
-</tr>
-
-<tr>
- <td><code>ramdisk.img</code></td>
- <td>The ramdisk image used to boot the system.</td>
- <td>Override using <code>-ramdisk <file></code></td>
-</tr>
-
-<tr>
- <td><code>system.img</code></td>
- <td>The <em>initial</em> Android system image.</td>
- <td>Override using <code>-image <file></code></td>
-</tr>
--->
-<tr>
- <td><code>userdata.img</code></td>
- <td>The <em>initial</em> user-data disk image</td>
- <td>Override using <code>-initdata <file></code>. Also see
-<code>-data <file></code>, below.</td>
-</tr>
-
-</table>
-
-<h3 id="runtimeimages">Runtime images: user data and SD card</h3>
-
-<p>At runtime, the emulator reads and writes data to two disk images: a
-user-data image and (optionally) an SD card image. These images emulate the user-data
-partition and removable storage media on actual device. </p>
-
-<p>The emulator provides a default user-data disk image. At startup, the emulator
-creates the default image as a copy of the system user-data image (user-data.img),
-described above. The emulator stores the new image with the files of the active AVD.</p>
-
-<!--
-<p>The emulator provides a startup option, <code>-datadir <dir></code>,
-that you can use to override the location under which the emulator looks for the runtime
-image files. </p>
--->
-
-<p>The emulator provides startup options to let you override the actual names and storage
-locations of the runtime images to load, as described in the following table. When you use one
-of these options, the emulator looks for the specified file(s) in the current working directory,
-in the AVD directory, or in a custom location (if you specified a path with the filename). </p>
-
-<table>
-<tr>
- <th width="10%" >Name</th>
- <th width="30%" >Description</th>
- <th width="40%" >Comments</th>
-</tr>
-<tr>
- <td><code>userdata-qemu.img</code></td>
- <td>An image to which the emulator writes runtime user-data for a unique user.</td>
- <td>Override using <code>-data <filepath></code>, where <code><filepath></code> is the
-path the image, relative to the current working directory. If you supply a filename only,
-the emulator looks for the file in the current working directory. If the file at <code><filepath></code> does
-not exist, the emulator creates an image from the default <code>userdata.img</code>, stores it under the name you
-specified, and persists user data to it at shutdown. </td>
-</tr>
-
-<tr>
- <td><code>sdcard.img</code></td>
- <td>An image representing an SD card inserted into the emulated device.</td>
- <td>Override using <code>-sdcard <filepath></code>, where <code><filepath></code> is the
-path the image, relative to the current working directory. If you supply a filename only,
-the emulator looks for the file in the current working directory. </td>
-</tr>
-
-</table>
-
-<h4>User-Data Image</h4>
-
-<p>Each emulator instance uses a writeable user-data image to store user- and
-session-specific data. For example, it uses the image to store a unique user's
-installed application data, settings, databases, and files. </p>
-
-<p>At startup, the emulator attempts to load a user-data image stored during
-a previous session. It looks for the file in the current working directory,
-in the AVD directory described in a previous section and at the custom location/name
-that you specified at startup. </p>
-
-<ul>
-<li>If it finds a user-data image, it mounts the image and makes it available
-to the system for reading and writing of user data. </li>
-<li>If it does not find one, it creates an image by copying the system user-data
-image (userdata.img), described above. At device power-off, the system persists
-the user data to the image, so that it will be available in the next session.
-Note that the emulator stores the new disk image at the location/name that you
-specify in <code>-data</code> startup option.</li>
-</ul>
-
-<p class="note"><strong>Note:</strong> Because of the AVD configurations used in the emulator,
-each emulator instance gets its own dedicated storage. There is no longer a need
-to use the <code>-d</code> option to specify an instance-specific storage area.</p>
-
-<h4>SD Card</h4>
-
-<P>Optionally, you can create a writeable disk image that the emulator can use
-to simulate removeable storage in an actual device. For information about how to create an
-emulated SD card and load it in the emulator, see <a href="#sdcard">SD Card Emulation</a></p>
-
-<p>You can also use the android tool to automatically create an SD Card image
-for you, when creating an AVD. For more information, see <a
-href="{@docRoot}tools/devices/managing-avds.html">Managing Virtual Devices with AVD
-Manager</a>.
-
-
-<h3 id="temporaryimages">Temporary Images</h3>
-
-<p>The emulator creates two writeable images at startup that it deletes at
-device power-off. The images are: </p>
-
-<ul>
- <li>A writable copy of the Android system image</li>
- <li>The <code>/cache</code> partition image</li>
-</ul>
-
-<p>The emulator does not permit renaming the temporary system image or
-persisting it at device power-off. </p>
-
-<p>The <code>/cache</code> partition image is initially empty, and is used by
-the browser to cache downloaded web pages and images. The emulator provides an
-<code>-cache <file></code>, which specifies the name of the file in which
-to persist the <code>/cache</code> image at device power-off. If <code><file>
-</code> does not exist, the emulator creates it as an empty file. </p>
-
-<p>You can also disable the use of the cache partition by specifying the
-<code>-nocache</code> option at startup. </p>
-
-
-<h2 id="emulatornetworking">Emulator Networking</h2>
-
-<p>The emulator provides versatile networking capabilities that you can use to
-set up complex modeling and testing environments for your application. The
-sections below introduce the emulator's network architecture and capabilities.
-</p>
-
-<h3 id="networkaddresses">Network Address Space</h3>
-
-<p>Each instance of the emulator runs behind a virtual router/firewall service
-that isolates it from your development machine's network interfaces and settings
-and from the internet. An emulated device can not see your development machine
-or other emulator instances on the network. Instead, it sees only that it is
-connected through Ethernet to a router/firewall.</p>
-
-<p>The virtual router for each instance manages the 10.0.2/24 network address
-space — all addresses managed by the router are in the form of
-10.0.2.<xx>, where <xx> is a number. Addresses within this space are
-pre-allocated by the emulator/router as follows:</p>
-
-<table>
- <tr>
- <th>Network Address</th>
- <th>Description</th>
- </tr>
- <tr>
- <td>10.0.2.1</td>
- <td>Router/gateway address </td>
- </tr>
- <tr>
- <td>10.0.2.2</td>
- <td>Special alias to your host loopback interface (i.e., 127.0.0.1 on your
-development machine)</td>
- </tr>
- <tr>
- <td>10.0.2.3</td>
- <td>First DNS server</td>
- </tr>
- <tr>
- <td>10.0.2.4 / 10.0.2.5 / 10.0.2.6</td>
- <td>Optional second, third and fourth DNS server (if any) </td>
- </tr>
- <tr>
- <td>10.0.2.15</td>
- <td>The emulated device's own network/ethernet interface</td>
- </tr>
- <tr>
- <td>127.0.0.1</td>
- <td>The emulated device's own loopback interface </td>
- </tr>
-</table>
-
-<p>Note that the same address assignments are used by all running emulator
-instances. That means that if you have two instances running concurrently on
-your machine, each will have its own router and, behind that, each will have an
-IP address of 10.0.2.15. The instances are isolated by a router and can
-<em>not</em> see each other on the same network. For information about how to
-let emulator instances communicate over TCP/UDP, see <a
-href="#connecting">Connecting Emulator Instances</a>.</p>
-
-<p>Also note that the address 127.0.0.1 on your development machine corresponds
-to the emulator's own loopback interface. If you want to access services running
-on your development machine's loopback interface (a.k.a. 127.0.0.1 on your
-machine), you should use the special address 10.0.2.2 instead.</p>
-
-<p>Finally, note that each emulated device's pre-allocated addresses are
-specific to the Android emulator and will probably be very different on real
-devices (which are also very likely to be NAT-ed, i.e., behind a
-router/firewall)</p>
-
-
-<h3 id="networkinglimitations">Local Networking Limitations</h3>
-
-<p>Android applications running in an emulator can connect to the network available on your
-workstation. However, they connect through the emulator, not directly to hardware, and the emulator
-acts like a normal application on your workstation. This means that the emulator, and thus your
-Android applications, are subject to some limitations:</p>
-
-<ul>
- <li>Communication with the emulated device may be blocked by a firewall
-program running on your machine.</li>
- <li>Communication with the emulated device may be blocked by another
-(physical) firewall/router to which your machine is connected.</li>
-</ul>
-
-<p>The emulator's virtual router should be able to handle all outbound TCP and
-UDP connections/messages on behalf of the emulated device, provided your
-development machine's network environment allows it to do so. There are no
-built-in limitations on port numbers or ranges except the one imposed by your
-host operating system and network.</p>
-
-<p>Depending on the environment, the emulator may not be able to support other
-protocols (such as ICMP, used for "ping") might not be supported. Currently, the
-emulator does not support IGMP or multicast. </p>
-
-<h3 id="redirection">Using Network Redirection</h3>
-
-<p>To communicate with an emulator instance behind its virtual router, you need
-to set up network redirection on the virtual router. Clients can then connect
-to a specified guest port on the router, while the router directs traffic
-to/from that port to the emulated device's host port. </p>
-
-<p>To set up the network redirection, you create a mapping of host and guest
-ports/addresses on the emulator instance. There are two ways to set up
-network redirection: using emulator console commands and using the ADB tool, as
-described below. </p>
-
-
-<h4 id="consoleredir">Setting up Redirection through the Emulator Console</h4>
-
-<p>Each emulator instance provides a control console the you can connect to, to
-issue commands that are specific to that instance. You can use the
-<code>redir</code> console command to set up redirection as needed for an
-emulator instance. </p>
-
-<p>First, determine the console port number for the target emulator instance.
-For example, the console port number for the first emulator instance launched is
-5554. Next, connect to the console of the target emulator instance, specifying
-its console port number, as follows: </p>
-
-<pre><code>telnet localhost 5554</code></pre>
-
-<p>Once connected, use the <code>redir</code> command to work with redirection.
-To add a redirection, use:</p>
-
-<pre><code>add <protocol>:<host-port>:<guest-port></code>
+<uses-feature android:name="android.hardware.type.watch" />
</pre>
-<p>where <code><protocol></code> is either <code>tcp</code> or <code>udp</code>,
-and <code><host-port></code> and <code><guest-port></code> sets the
-mapping between your own machine and the emulated system, respectively. </p>
+<p>There are also settings for camera, location, audio, microphone, phone,
+networking, TV, touchscreen, and more. For more information, see
+<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">
+<uses-feature></a>.</p>
-<p>For example, the following command sets up a redirection that handles all
-incoming TCP connections to your host (development) machine on 127.0.0.1:5000
-and will pass them through to the emulated system's 10.0.2.15:6000.:</p>
+<h3 id="system">System images</h3>
-<pre>redir add tcp:5000:6000</pre>
-
-<p>To delete a redirection, you can use the <code>redir del</code> command. To
-list all redirection for a specific instance, you can use <code>redir
-list</code>. For more information about these and other console commands, see
-<a href="#console">Using the Emulator Console</a>. </p>
-
-<p>Note that port numbers are restricted by your local environment. this typically
-means that you cannot use host port numbers under 1024 without special
-administrator privileges. Also, you won't be able to set up a redirection for a
-host port that is already in use by another process on your machine. In that
-case, <code>redir</code> generates an error message to that effect. </p>
-
-<h4 id="adbredir">Setting Up Redirection through ADB</h4>
-
-<p>The Android Debug Bridge (ADB) tool provides port forwarding, an alternate
-way for you to set up network redirection. For more information, see <a
-href="{@docRoot}tools/help/adb.html#forwardports">Forwarding Ports</a> in the ADB
-documentation.</p>
-
-<p>Note that ADB does not currently offer any way to remove a redirection,
-except by killing the ADB server.</p>
-
-
-<h3 id="dns">Configuring the Emulator's DNS Settings</h3>
-
-<p>At startup, the emulator reads the list of DNS servers that your system is
-currently using. It then stores the IP addresses of up to four servers on this
-list and sets up aliases to them on the emulated addresses 10.0.2.3, 10.0.2.4,
-10.0.2.5 and 10.0.2.6 as needed. </p>
-
-<p>On Linux and OS X, the emulator obtains the DNS server addresses by parsing
-the file <code>/etc/resolv.conf</code>. On Windows, the emulator obtains the
-addresses by calling the <code>GetNetworkParams()</code> API. Note that this
-usually means that the emulator ignores the content of your "hosts" file
-(<code>/etc/hosts</code> on Linux/OS X, <code>%WINDOWS%/system32/HOSTS</code>
- on Windows).</P>
-
-<p>When starting the emulator at the command line, you can also use the
-<code>-dns-server <serverList></code> option to manually specify the
-addresses of DNS servers to use, where <serverList> is a comma-separated
-list of server names or IP addresses. You might find this option useful if you
-encounter DNS resolution problems in the emulated network (for example, an
-"Unknown Host error" message that appears when using the web browser).</p>
-
-
-<h3 id="proxy">Using the Emulator with a Proxy</h3>
-
-<p>If your emulator must access the Internet through a proxy server, you can use
-the <code>-http-proxy <proxy></code> option when starting the emulator, to
-set up the appropriate redirection. In this case, you specify proxy information
-in <code><proxy></code> in one of these formats:</p>
-
-<pre>http://<machineName>:<port></pre>
-
-<p>or</p>
-
-<pre>http://<username>:<password>@<machineName>:<port></pre>
-
-<p>The <code>-http-proxy</code> option forces the emulator to use the specified
-HTTP/HTTPS proxy for all outgoing TCP connections. Redirection for UDP is not
-currently supported.</p>
-
-<p>Alternatively, you can define the environment variable
-<code>http_proxy</code> to the value you want to use for
-<code><proxy></code>. In this case, you do not need to specify a value for
-<code><proxy></code> in the <code>-http-proxy</code> command — the
-emulator checks the value of the <code>http_proxy</code> environment variable at
-startup and uses its value automatically, if defined. </p>
-
-<p>You can use the <code>-verbose-proxy</code> option to diagnose proxy
-connection problems.</p>
-
-
-<h3 id="connecting">Interconnecting Emulator Instances</h3>
-
-<p>To allow one emulator instance to communicate with another, you must set up
-the necessary network redirection as illustrated below. </p>
-
-<p>Assume that your environment is</p>
-
-<ul>
- <li>A is you development machine</li>
- <li>B is your first emulator instance, running on A</li>
- <li>C is your second emulator instance, also running on A</li>
-</ul>
-
-<p>and you want to run a server on B, to which C will connect, here is how you
-could set it up: </p>
-
-<ol>
- <li>Set up the server on B, listening to
-<code>10.0.2.15:<serverPort></code></li>
- <li>On B's console, set up a redirection from
-<code>A:localhost:<localPort></code> to <code>
-B:10.0.2.15:<serverPort></code></li>
- <li>On C, have the client connect to <code>10.0.2.2:<localPort></code></li>
-</ol>
-
-<p>For example, if you wanted to run an HTTP server, you can select
-<code><serverPort></code> as 80 and <code><localPort></code> as
-8080:</p>
-
-<ul>
- <li>B listens on 10.0.2.15:80</li>
- <li>On B's console, issue <code>redir add tcp:8080:80</code></li>
- <li>C connects to 10.0.2.2:8080</li>
-</ul>
-
-<h3 id="calling">Sending a Voice Call or SMS to Another Emulator Instance</h3>
-
-<p>The emulator automatically forwards simulated voice calls and SMS messages from one instance to
-another. To send a voice call or SMS, use the dialer application or SMS application, respectively,
-from one of the emulators.</p>
-
-<p>To initiate a simulated voice call to another emulator instance:</p>
-<ol>
-<li>Launch the dialer application on the originating emulator instance.</li>
-<li>As the number to dial, enter the console port number of the instance you'd like to call. You can determine
- the console port number of the target instance by checking its window title, where the
- console port number is reported as "Android Emulator (<port>). </li>
-<li>Press "Dial". A new inbound call appears in the target emulator instance. </li>
-</ol>
-
-<p>To send an SMS message to another emulator instance, launch the SMS application (if available). Specify the console port number of the target emulator instance as as the SMS address, enter the message text, and send the message. The message is delivered to the target emulator instance. </p>
-
-<p>You can also connect to an emulator instance's console to simulate an incoming voice call or SMS. For more information, see <a href="#telephony">Telephony Emulation</a> and <a href="#sms">SMS Emulation</a>.
-
-
-<h2 id="console">Using the Emulator Console</h2>
-
-<p>Each running emulator instance provides a console that lets you query and control the emulated
-device environment. For example, you can use the console to manage port redirection, network
-characteristics, and telephony events while your application is running on the emulator. To
-access the console and enter commands, use telnet to connect to the console's port number.</p>
-
-<p>To connect to the console of any running emulator instance at any time, use this command: </p>
-
-<pre>telnet localhost <console-port></pre>
-
-<p>An emulator instance occupies a pair of adjacent ports: a console port and an {@code adb} port.
-The port numbers differ by 1, with the {@code adb} port having the higher port number. The console
-of the first emulator instance running on a given machine uses console port 5554 and {@code adb}
-port 5555. Subsequent instances use port numbers increasing by two — for example, 5556/5557,
-5558/5559, and so on. Up to 16 concurrent emulator instances can run a console facility. </p>
-
-<p>To connect to the emulator console, you must specify a valid console port. If multiple emulator instances are running, you need to determine the console port of the emulator instance you want to connect to. You can find the instance's console port listed in the title of the instance window. For example, here's the window title for an instance whose console port is 5554:</p>
-
-<p><code>Android Emulator (5554)</code></p>
-
-<p>Alternatively, you can use the <code>adb devices</code> command, which prints a list of running emulator instances and their console port numbers. For more information, see <a href="{@docRoot}tools/help/adb.html#devicestatus">Querying for Emulator/Device Instances</a> in the adb documentation.</p>
-
-<p class="note">Note: The emulator listens for connections on ports 5554-5587 and accepts connections only from localhost.</p>
-
-<p>Once you are connected to the console, you can then enter <code>help [command]</code> to see a list of console commands and learn about specific commands. </p>
-
-<p>To exit the console session, use <code>quit</code> or <code>exit</code>.</p>
-
-<p>The following sections below describe the major functional areas of the console.</p>
-
-
-<h3 id="portredirection">Port Redirection</h3>
-
-<p>You can use the console to add and remove port redirection while the emulator is running. After
-you connect to the console, manage port redirection by entering the following command:</p>
-
-<pre>redir <list|add|del> </pre>
-
-<p>The <code>redir</code> command supports the subcommands listed in the table below. </p>
-
-<table>
-<tr>
- <th width="25%" >Subcommand
- <th width="30%" >Description</th>
- <th width="35%">Comments</th>
-</tr>
-
- <tr>
- <td><code>list</code></td>
- <td>List the current port redirection.</td>
- <td> </td>
- </tr>
-
-
-<tr>
- <td><code>add <protocol>:<host-port>:<guest-port></code></td>
- <td>Add a new port redirection.</td>
-<td><ul><li><protocol> must be either "tcp" or "udp"</li>
-<li><host-port> is the port number to open on the host</li>
-<li><guest-port> is the port number to route data to on the emulator/device</li>
-</ul></td>
-</tr>
-<tr>
- <td><code>del <protocol>:<host-port></code></td>
- <td>Delete a port redirection.</td>
-<td>The meanings of <protocol> and <host-port> are listed in the previous row.</td>
-</tr>
-</table>
-
-
-<h3 id="geo">Geo Location Provider Emulation</h3>
-
-<p>You can use the console to set the geographic location reported to the applications running
-inside an emulator. Use the <code>geo</code> command to send a simple GPS fix to the
-emulator, with or without NMEA 1083 formatting:</p>
-
-<pre>geo <fix|nmea></pre>
-
-<p>The <code>geo</code> command supports the subcommands listed in the table below.</p>
-
-<table>
-<tr>
- <th width="25%">Subcommand</th>
- <th width="30%">Description</th>
- <th width="35%">Comments</th>
-</tr>
-
- <tr>
- <td><code>fix <longitude> <latitude> [<altitude>]</code></td>
- <td>Send a simple GPS fix to the emulator instance.</td>
- <td>Specify longitude and latitude in decimal degrees. Specify altitude in meters.</td>
- </tr>
-<tr>
- <td><code>nmea <sentence></code></td>
- <td>Send an NMEA 0183 sentence to the emulated device, as if it were sent from an emulated GPS modem.</td>
-<td><code><sentence></code> must begin with '$GP'. Only '$GPGGA' and '$GPRCM' sentences are currently supported.</td>
-</tr>
-</table>
-
-<p>You can issue the <code>geo</code> command as soon as an emulator instance is running. The
-emulator sets the location you enter by creating a mock location provider. This provider responds to
-location listeners set by applications, and also supplies the location to the {@link
-android.location.LocationManager}. Any application can query the location manager to obtain the
-current GPS fix for the emulated device by calling:
-
-<pre>LocationManager.getLastKnownLocation("gps")</pre>
-
-<p>For more information about the Location Manager, see {@link android.location.LocationManager}.
+<p>The Android Emulator runs a full
+Android system stack, down to the kernel level, that includes a set of
+preinstalled apps (such as the dialer) that you can access from your
+apps. You can choose which version of the Android system you want to
+run in the emulator when creating AVDs.
</p>
-<h3 id="events">Hardware Events Emulation</h3>
+<p>The Android system images available through the AVD Manager contain
+code for the Android Linux kernel, the native libraries, the VM, and the
+various Android packages (such as the Android framework and preinstalled
+apps).</p>
-<p>The {@code event} console commands sends hardware events to the emulator. The syntax for this
-command is as follows:</p>
-
-<pre>event <send|types|codes|text></pre>
-
-<p>The <code>event</code> command supports the subcommands listed in the table below. </p>
-
-<table>
-<tr>
- <th width="25%" >Subcommand
- <th width="30%" >Description</th>
- <th width="35%">Comments</th>
-</tr>
-
- <tr>
- <td><code>send <type>:<code>:<value> [...]</code></td>
- <td>Send one or more events to the Android kernel. </td>
- <td>You can use text names or integers for <code><type></code> and <code><value></code>.</td>
- </tr>
-<tr>
- <td><code>types</code></td>
- <td>List all <code><type></code> string aliases supported by the <code>event</code> subcommands.</td>
-<td> </td>
-</tr>
-<tr>
- <td><code>codes <type></code></td>
- <td>List all <code><codes></code> string aliases supported by the <code>event</code>
- subcommands for the specified <code><type></code>.</td>
-<td> </td>
-</tr>
-<tr>
- <td><code>event text <message></code></td>
- <td>Simulate keypresses to send the specified string of characters as a message,</td>
-<td>The message must be a UTF-8 string. Unicode posts will be reverse-mapped according to the current device keyboard. Unsupported characters will be discarded silently.</td>
-</tr>
-</table>
-
-
-<h3 id="power">Device Power Characteristics</h3>
-
-<p>The {@code power} command controls the power state reported by the emulator to applications. The
-syntax for this command is as follows: </p>
-
-<pre>power <display|ac|status|present|health|capacity></pre>
-
-<p>The <code>event</code> command supports the subcommands listed in the table below. </p>
-
-<table>
-<tr>
- <th width="25%" >Subcommand </th>
- <th width="30%" >Description</th>
- <th width="35%">Comments</th>
-</tr>
-
- <tr>
- <td><code>display</code></td>
- <td>Display battery and charger state.</td>
- <td> </td>
- </tr>
-<tr>
- <td><code>ac <on|off></code></td>
- <td>Set AC charging state to on or off. </td>
-<td> </td>
-</tr>
-<tr>
- <td><code>status <unknown|charging|discharging|not-charging|full></code></td>
- <td>Change battery status as specified.</td>
-<td> </td>
-</tr>
-
-<tr>
- <td><code>present <true|false></code></td>
- <td>Set battery presence state.</td>
-<td> </td>
-</tr>
-<tr>
- <td><code>health <unknown|good|overheat|dead|overvoltage|failure></code></td>
- <td>Set battery health state.</td>
-<td> </td>
-</tr>
-<tr>
- <td><code>capacity <percent></code></td>
- <td>Set remaining battery capacity state (0-100).</td>
-<td> </td>
-</tr>
-</table>
-
-
-<h3 id="netstatus">Network Status</h3>
-
-<p>You can use the console to check the network status and current delay and speed characteristics. To do so, connect to the console and use the <code>netstatus</code> command. Here's an example of the command and its output. </p>
-
-<pre>network status
-</pre>
-
-
-<h3 id="netdelay">Network Delay Emulation</h3>
-
-<p>The emulator lets you simulate various network latency levels, so that you can test your
-application in an environment more typical of the actual conditions in which it will run. You can
-set a latency level or range at emulator startup or you can use the console to change the latency,
-while the application is running in the emulator. </p>
-
-<p>To set latency at emulator startup, use the <code>-netdelay</code> emulator option with a
-supported <code><delay></code> value, as listed in the table below. Here are some
-examples:</p>
-
-<pre>emulator -netdelay gprs
-emulator -netdelay 40 100</pre>
-
-<p>To make changes to network delay while the emulator is running, connect to the console and use
-the <code>netdelay</code> command with a supported <code><delay></code> value from the table
-below.</p>
-
-<pre>network delay gprs</pre>
-
-<p>The format of network <delay> is one of the following (numbers are milliseconds):</p>
-
-<table style="clear:right;width:100%;">
-<tr>
- <th width="30%" >Value</th>
- <th width="35%" >Description</th><th width="35%">Comments</th></tr>
-
- <tr><td><code>gprs</code></td><td>GPRS</td>
- <td>(min 150, max 550)</td>
- </tr>
-
-<tr><td><code>edge</code></td><td>EDGE/EGPRS</td>
-<td>(min 80, max 400)</td>
-</tr>
-<tr><td><code>umts</code></td><td>UMTS/3G</td>
-<td>(min 35, max 200)</td>
-</tr>
-<tr><td><code>none</code></td><td>No latency</td><td>(min 0, max 0)</td></tr>
-<tr><td><code><num></code></td>
-<td>Emulate an exact latency (milliseconds).</td>
-<td> </td></tr>
-<tr><td><code><min>:<max></code></td>
-<td>Emulate an specified latency range (min, max milliseconds).</td>
-<td> </td></tr>
-</table>
-
-
-<h3 id="netspeed">Network Speed Emulation</h3>
-
-<p>The emulator also lets you simulate various network transfer rates.
-You can set a transfer rate or range at emulator startup or you can use the console to change the
-rate, while the application is running in the emulator.</p>
-
-<p>To set the network speed at emulator startup, use the <code>-netspeed</code> emulator option with a supported
-<code><speed></code> value, as listed in the table below. Here are some examples:</p>
-
-<pre>emulator -netspeed gsm
-emulator -netspeed 14.4 80</pre>
-
-<p>To make changes to network speed while the emulator is running, connect to the console and use
-the <code>netspeed</code> command with a supported <code><speed></code> value from the table
-below.</p>
-
-<pre>network speed 14.4 80</pre>
-
-<p>The format of network <code><speed></code> is one of the following (numbers are
-kilobits/sec):</p>
-<table style="clear:right;width:100%;">
-<tbody>
-<tr>
- <th width="30%">Value</th>
- <th width="35%">Description</th><th width="35%">Comments</th></tr>
-
- <tr>
- <td><code>gsm</code></td>
- <td>GSM/CSD</td><td>(Up: 14.4, down: 14.4)</td></tr>
-<tr>
- <td><code>hscsd</code></td>
- <td>HSCSD</td><td>(Up: 14.4, down: 43.2)</td></tr>
-<tr>
- <td><code>gprs</code></td>
- <td>GPRS</td><td>(Up: 40.0, down: 80.0)</td></tr>
-<tr>
- <td><code>edge</code></td>
- <td>EDGE/EGPRS</td>
- <td>(Up: 118.4, down: 236.8)</td>
-</tr>
-<tr>
- <td><code>umts</code></td>
- <td>UMTS/3G</td><td>(Up: 128.0, down: 1920.0)</td></tr>
-<tr>
- <td><code>hsdpa</code></td>
- <td>HSDPA</td><td>(Up: 348.0, down: 14400.0)</td></tr>
-<tr>
- <td><code>full</code></td>
- <td>no limit</td><td>(Up: 0.0, down: 0.0)</td></tr>
-<tr>
- <td><code><num></code></td>
- <td>Set an exact rate used for both upload and download.</td><td></td></tr>
-<tr>
- <td><code><up>:<down></code></td>
- <td>Set exact rates for upload and download separately.</td><td></td></tr>
-</table>
-
-
-<h3 id="telephony">Telephony Emulation</h3>
-
-<p>The Android emulator includes its own GSM emulated modem that lets you simulate telephony
-functions in the emulator. For example, you can simulate inbound phone calls, establish data
-connections and terminate them. The Android system handles simulated calls exactly as it would
-actual calls. The emulator does not support call audio.</p>
-
-<p>You can use the {@code gsm} command to access the emulator's telephony functions after connecting
-to the console. The syntax for this command is as follows:</p>
-
-<pre>gsm <call|accept|busy|cancel|data|hold|list|voice|status> </pre>
-
-<p>The <code>gsm</code> command supports the subcommands listed in the table below. </p>
-<table>
- <tr>
- <th>Subcommand </th>
- <th width="25%">Description</th>
- <th>Comments</th>
- </tr>
- <tr>
- <td><code>call <phonenumber></code></td>
- <td>Simulate an inbound phone call from <phonenumber>.</td>
- <td> </td>
- </tr>
- <tr>
- <td><code>accept <phonenumber></code></td>
- <td>Accept an inbound call from <phonenumber> and change the call's state "active".</td>
- <td>You can change a call's state to "active" only if its current state is "waiting" or "held".</td>
- </tr>
- <tr>
- <td><code>busy <phonenumber></code></td>
- <td>Close an outbound call to <phonenumber> and change the call's state to "busy".</td>
- <td>You can change a call's state to "busy" only if its current state is "waiting".</td>
- </tr>
- <tr>
- <td><code>cancel <phonenumber></code></td>
- <td>Terminate an inbound or outbound phone call to/from <phonenumber>.</td>
- <td> </td>
- </tr>
- <tr>
- <td><code>data <state></code></td>
- <td>Change the state of the GPRS data connection to <state>.</td>
- <td>Supported <state> values are:<br />
+<h3 id="dependencies">Dependencies and prerequisites</h3>
+<p>The Android Emulator has the following requirements:</p>
<ul>
- <li><code>unregistered</code> -- No network available</li>
- <li><code>home</code> -- On local network, non-roaming</li>
- <li><code>roaming</code> -- On roaming network</li>
- <li><code>searching</code> -- Searching networks</li>
- <li><code>denied</code> -- Emergency calls only</li>
- <li><code>off</code> -- Same as 'unregistered'</li>
- <li><code>on</code> -- same as 'home'</li>
- </ul>
- </td>
- </tr>
- <tr>
- <td><code>hold</code></td>
- <td>Change the state of a call to "held". </td>
- <td>You can change a call's state to "held" only if its current state is "active" or "waiting". </td>
- </tr>
- <tr>
- <td><code>list</code></td>
- <td>List all inbound and outbound calls and their states.</td>
- <td> </td>
- </tr>
- <tr>
- <td><code>voice <state></code></td>
- <td>Change the state of the GPRS voice connection to <state>.</td>
- <td>Supported <state> values are:<br />
- <ul>
- <li><code>unregistered</code> -- No network available</li>
- <li><code>home</code> -- On local network, non-roaming</li>
- <li><code>roaming</code> -- On roaming network</li>
- <li><code>searching</code> -- Searching networks</li>
- <li><code>denied</code> -- Emergency calls only</li>
- <li><code>off</code> -- Same as 'unregistered'</li>
- <li><code>on</code> -- Same as 'home'</li>
- </ul>
- </td>
- </tr>
-
- <tr>
- <td><code>status</code></td>
- <td>Report the current GSM voice/data state.</td>
- <td>Values are those described for the <code>voice</code> and <code>data</code> commands.</td>
- </tr>
-</table>
-
-
-<h3 id="sms">SMS Emulation</h3>
-
-<p>The Android emulator console lets you generate an SMS message and direct it to an emulator
-instance. Once you connect to an emulator instance, you can generate an emulated incoming SMS using
-the following command:</p>
-
-<pre>sms send <senderPhoneNumber> <textmessage></pre>
-
-<p>where <code><senderPhoneNumber></code> contains an arbitrary numeric string. </p>
-
-<p>The console forwards the SMS message to the Android framework, which passes it through to an application that handles that message type. </p>
-
-
-<h3 id="vm">VM State</h3>
-
-<p>You can use the <code>vm</code> command to control the VM on an emulator instance. The syntax for
-this command is as follows: </p>
-
-<pre>vm <start|stop|status></pre>
-
-<p>The <code>vm</code> command supports the subcommands listed in the table below. </p>
-
-<table>
-<tr>
- <th width="25%">Subcommand</th>
- <th width="30%">Description</th>
- <th width="35%">Comments</th>
-</tr>
-<tr>
- <td><code>start</code></td>
- <td>Start the VM on the instance. </td>
- <td> </td>
-</tr>
-<tr>
- <td><code>stop</code></td>
- <td>Stop the VM on the instance. </td>
- <td> </td>
-</tr>
-<tr>
- <td><code>start</code></td>
- <td>Display the current status of the VM (running or stopped). </td>
- <td> </td>
-</tr>
-</table>
-
-
-<h3 id="window">Emulator Window</h3>
-
-<p>You can use the <code>window</code> command to manage the emulator window. The syntax for this
-command is as follows: </p>
-
-<pre>window <scale></pre>
-
-<p>The <code>vm</code> command supports the subcommands listed in the table below. </p>
-
-<table>
-<tr>
- <th width="25%">Subcommand</th>
- <th width="30%">Description</th>
- <th width="35%">Comments</th>
-</tr>
-<tr>
- <td><code>scale <scale></code></td>
- <td>Scale the emulator window.</td>
- <td>A number between 0.1 and 3 that sets the scaling factor. You can
- also specify scale as a DPI value if you add the suffix "dpi" to the scale value. A value of "auto"
- tells the emulator to select the best window size.</td>
-</tr>
-</table>
-
-
-<h3 id="terminating">Terminating an Emulator Instance</h3>
-
-<p>You can terminate an emulator instance through the console, using the <code>kill</code> command.</p>
-
-
-<h2 id="limitations">Emulator Limitations</h2>
-
-<p>The functional limitations of the emulator include: </p>
-<ul>
- <li>No support for placing or receiving actual phone calls. You can simulate phone calls (placed
- and received) through the emulator console, however. </li>
- <li>No support for USB connections</li>
- <li>No support for device-attached headphones</li>
- <li>No support for determining network connected state</li>
- <li>No support for determining battery charge level and AC charging state</li>
- <li>No support for determining SD card insert/eject</li>
- <li>No support for Bluetooth</li>
+ <li>Android Studio 2.0 or higher</li>
+ <li>SDK Tools 25.0.10 or higher</li>
+ <li><a href="{@docRoot}sdk/index.html#Requirements">System
+ requirements</a></li>
+ <li>Newly created AVDs to replace any AVDs for emulator 24.0.<em>x</em> or
+ lower</li>
+ <li>Active network connection for certain operations, such as testing app
+ features that require it</li>
+ <li>adb integration enabled through <strong>Tools</strong> >
+ <strong>Android</strong> > <strong>Enable ADB Integration</strong>
+ </li>
</ul>
+<h3 id="limitations">What's not supported</h3>
-<h2 id="troubleshooting">Troubleshooting Emulator Problems</h2>
+<p>The Android Emulator supports most features of a device, but doesn't
+include virtual hardware for:</p>
+<ul>
+<li>WiFi</li>
+<li>Bluetooth</li>
+<li>NFC</li>
+<li>SD card insert/eject</li>
+<li>Device-attached headphones</li>
+<li>USB</li>
+</ul>
+<p>The watch emulator for Android Wear doesn't support the Overview
+(Recent Apps) button, D-pad, and fingerprint sensor.</p>
-<p>The {@code adb} utility sees the emulator as an actual physical device. For this reason, you
-might have to use the {@code -d} flag with some common {@code adb} commands, such as
-<code>install</code>. The {@code -d} flag lets you specify which of several connected devices to use
-as the target of a command. If you don't specify {@code -d}, the emulator targets the first
-device in its list. For more information about {@code adb}, see <a
-href="{@docRoot}tools/help/adb.html">Android Debug Bridge</a>.</p>
+<p>While most end users of phones and tablets tend to use earlier API levels,
+Android Wear and Android TV users tend to use the latest releases. Using recent
+releases can give you a better experience using the emulator.
+</p>
-<p>For emulators running on Mac OS X, if you see an error {@code Warning: No DNS servers found}
-when starting the emulator, check to see whether you have an <code>/etc/resolv.conf</code> file. If
-not, please run the following line in a command window:</p>
- <pre>ln -s /private/var/run/resolv.conf /etc/resolv.conf</pre>
+<h2 id="runningapp">Running an App in the Android Emulator</h2>
-<p>See <a href="{@docRoot}resources/faq/index.html">Frequently Asked Questions</a> for more
-troubleshooting information. </p>
+<p>You can run an app from an Android Studio project. Or, you can run an app
+that's been installed on the emulator as you would run any app on a device.</p>
+
+<p>To start the emulator and run an app in your project:</p>
+<ol>
+<li>Open an Android Studio project and select Run <img src="{@docRoot}images/tools/e-irun.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Run icon" />.</li>
+ <p>The <em>Select Deployment Target</em> dialog appears.</p>
+<img src="{@docRoot}images/tools/e-selectdeploymenttarget.png"
+style="height:250px" alt="Select Deployment Target dialog" />
+<li>If you receive an error or warning message at the top of the dialog, click
+the link to correct the problem or get more information.</li>
+<p>The <strong>No USB devices or running emulators detected</strong> warning
+means that you don’t currently have any emulators running, or any detected
+hardware devices connected to your computer. If you
+don’t have hardware devices connected to your computer, or any emulators
+running, you can ignore it. </p>
+<p>Some errors you must fix before you can continue, such as certain Hardware
+Accelerated Execution Manager (Intel® HAXM) errors.</p>
+<li>In the <em>Select Deployment Target</em> dialog, select an existing emulator
+definition, and then click <strong>OK</strong>.</p>
+<p>If you don’t see a definition you want to use, click <strong>Create New
+Emulator</strong> to launch the AVD Manager. After you define a new AVD, in
+the <em>Select Deployment
+Target</em> dialog, click <strong>OK</strong>.</p>
+<p>If you want to use this emulator definition as the default for your project,
+select <strong>Use same selection for future launches</strong>.</p>
+<p>The emulator launches and displays your app.</p>
+<li>Test your app in the emulator.</li>
+<p>You can use the features described in the following sections:</p>
+<ul>
+<li><a href="#navigate">Navigating on the Screen</a></li>
+<li><a href="#tasks">Performing Basic Tasks in the Emulator</a></li>
+<li><a href="#extended">Working With Extended Controls, Settings, and Help</a></li>
+</ul>
+<li>To close the emulator, click Close <img src="{@docRoot}images/tools/e-iclose.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Close icon" />.</li>
+ <p>The emulator device stores the installed app so you can run it again, if
+ needed. You need to uninstall an app to remove it. If you run the project
+ again on the same emulator, it replaces the app with the new version.</p>
+</ol>
+
+<h2 id="runningemulator">Launching the Android Emulator Without Running an App</h2>
+
+<p>To start the emulator:</p>
+<ol>
+<li><a href="{@docRoot}tools/devices/managing-avds.html">Open the AVD Manager</a>.</li>
+<li>Double-click an AVD, or click Run <img src="{@docRoot}images/tools/e-irun.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Run icon" />.</li>
+ <p>The Android Emulator appears.</p>
+ <p>While the emulator is running, you can run Android Studio projects and
+ choose the
+ emulator as the target device. You can also drag one or more APKs onto the
+ emulator to install them, and then run them.</p>
+</ol>
+
+
+<h2 id="navigate">Navigating on the Screen</h2>
+
+<p>Use your computer mouse pointer to mimic your finger on the touchscreen;
+select menu items and input fields; and click buttons and controls.
+Use your computer keyboard to type characters and enter emulator shortcuts.</p>
+<table border="0" style="clear:left;">
+<tr>
+ <th scope="col">Feature</th>
+ <th scope="col">Description</th>
+ </tr>
+
+ <tr>
+ <td>Swipe the screen</td>
+ <td>Point to the screen, press and hold the primary mouse button, swipe
+ across the screen, and then release.</td>
+ </tr>
+ <tr>
+ <td>Drag an item</td>
+ <td>Point to an item on the screen, press and hold the primary mouse
+ button, move the item, and then release.</td>
+ </tr>
+ <tr>
+ <td>Tap <div>(touch)</div></td>
+ <td>Point to the screen, press the primary mouse button, and then release.
+ For example, you could click a text field to start typing in it, select an
+ app, or press a button.</td>
+ </tr>
+ <tr>
+ <td>Double tap</td>
+ <td>Point to the screen, press the primary mouse button quickly twice,
+ and then release.</td>
+ </tr>
+ <tr>
+ <td>Touch and hold</td>
+ <td>Point to an item on the screen, press the primary mouse button, hold,
+ and then release. For example, you could open options for an item. </td>
+ </tr>
+ <tr>
+ <td>Type</td>
+ <td>You can type in the emulator by using your computer keyboard, or using
+ a keyboard that pops up on the emulator screen. For example, you could
+ type in a text field after you selected it.</td>
+ </tr>
+ <tr>
+ <td><nobr>Pinch and spread</nobr></td>
+ <td><div>Pressing Alt or Option (⌥) brings up a pinch gesture multi-touch
+ interface. The mouse acts as the first finger, and across the anchor point
+ is the second finger. Drag the cursor to move the first point.</div>
+ <div>Clicking the left mouse button acts like touching down both points, and
+ releasing acts like picking both up.</div></td>
+ </tr>
+</table>
+
+<h2 id="tasks">Performing Basic Tasks in the Emulator</h2>
+
+<p>The panel on the right side of the emulator lets you perform various tasks.
+You can also drag files onto the emulator to install apps and download files.
+</p>
+<table border="0" style="clear:left;">
+ <tr>
+ <th scope="col">Feature</th>
+ <th scope="col">Description</th>
+ <th scope="col">Keyboard Shortcut</th>
+ </tr>
+ <tr>
+ <td>Close<br><img src="{@docRoot}images/tools/e-iclose.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Close icon" /></td>
+ <td>Close the emulator.</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>Minimize<br><img src="{@docRoot}images/tools/e-iminimize.png"
+ style="vertical-align:sub;margin:0;height:9px" alt="Minimize icon" /></td>
+ <td>Minimize the emulator window.</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>Resize</td>
+ <td>Resize the emulator as you would any other operating system window. The
+emulator maintains an aspect ratio appropriate for your device.</td>
+ <td>⌘↑ and ⌘↓</td>
+ </tr>
+ <tr>
+ <td>Power<br><img src="{@docRoot}images/tools/e-ipower.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Power icon" /></td>
+ <td>Click to turn the screen on or off.<br>Click and hold to turn the device
+ on or off. </td>
+ <td><div>Ctrl+P</div> <div>⌘P</div></td>
+ </tr>
+ <tr>
+ <td>Volume Up<br><img src="{@docRoot}images/tools/e-ivolumeup.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Volume Up icon" /></td>
+ <td>Click to view a slider control and turn the volume up. Click again to
+ turn it up more, or use the slider control to change the volume. </td>
+ <td><div>Ctrl+=</div><div>⌘=</div></td>
+ </tr>
+ <tr>
+ <td>Volume Down<br><img src="{@docRoot}images/tools/e-ivolumedown.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Volume Down icon" /></td>
+ <td>Click to view a slider control and turn the volume down. Click again to
+ turn it down more, or use the slider control to change the volume. </td>
+ <td><div>Ctrl+-</div><div>⌘-<div></td>
+ </tr>
+ <tr>
+ <td>Rotate Left<br><img src="{@docRoot}images/tools/e-irotateleft.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Rotate Left icon" /></td>
+ <td>Rotate the phone 90 degrees counterclockwise.</td>
+ <td><div>Ctrl+Left</div><div>⌘←</div></td>
+ </tr>
+ <tr>
+ <td>Rotate Right<br><img src="{@docRoot}images/tools/e-irotateright.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Rotate Right icon" /></td>
+ <td>Rotate the phone 90 degrees clockwise.</td>
+ <td><div>Ctrl+Right</div><div>⌘→</div></td>
+ </tr>
+ <tr>
+ <td>Take Screenshot<br><img src="{@docRoot}images/tools/e-itakescreenshot.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Take Screenshot icon" />
+ </td>
+ <td>Click to take a screenshot of the device. The default save location is
+ your computer desktop. To change the save location, select
+ <strong>…</strong> > <strong>Settings</strong>. The emulator creates a
+ file with the name <code>Screenshot_<em>yyyymmdd-hhmmss</em>.png</code>
+ using the year, month, day, hour, minute, and second of the capture, for
+ example, <code>Screenshot_20160219-145848.png</code>. </td>
+ <td><div>Ctrl+S</div><div>⌘S<div></td>
+ </tr>
+ <tr>
+ <td><nobr>Enter Zoom Mode</nobr><br><img src="{@docRoot}images/tools/e-izoom.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Enter Zoom Mode icon" />
+ </td>
+ <td><p>Click so the cursor changes to the zoom icon:</p>
+<ul>
+ <li> Left-click the screen to zoom in by 25%, up to a maximum of about twice
+ the screen resolution of the virtual device.
+ <li> Right-click to zoom out.
+ <li> Left-click and drag to select a box-shaped area to zoom in on.
+ <li> Right-click and drag a selection box to reset to default zoom.
+ <li> Ctrl-click to touch the screen while in zoom mode.
+</ul>
+<p>Click Enter Zoom Mode again to return to normal screen size.</p></td>
+ <td><div>Ctrl+Z</div><div>⌘Z</div>
+ <div>While in zoom mode:</div>
+ <div>Ctrl+Up</div><div>Ctrl+Down</div>
+ <div>Ctrl+Shift+Up</div><div>Ctrl+Shift+Down</div>
+ <div>Ctrl+Shift+Left</div><div>Ctrl+Shift+Right</div>
+ <div>⌘↑ and ⌘↓</div>
+ <div>⇧⌘↑ and ⇧⌘↓</div>
+ <div>⇧⌘← and ⇧⌘→</div></td>
+ </tr>
+ <tr>
+ <td>Back<br><img src="{@docRoot}images/tools/e-iback.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Back icon" /></td>
+ <td>Return to the previous screen, or close a dialog box, an options menu,
+ the Notifications panel, or the onscreen keyboard. </td>
+ <td><div>Ctrl+Backspace</div>
+ <div>⌘⌫</div></td>
+ </tr>
+ <tr>
+ <td>Home<br><img src="{@docRoot}images/tools/e-ihome.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Home icon" /></td>
+ <td>Return to the Home screen. Press and hold to open the item specific to
+ your API level. </td>
+ <td><div>Ctrl+H</div><div>⌘⇧H</div></td>
+ </tr>
+ <tr>
+ <td><div>Overview<br><img src="{@docRoot}images/tools/e-ioverview.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Overview icon" /></div>
+ <div>(Recent Apps)</div></td>
+ <td>Tap to open a list of thumbnail images of apps you’ve worked with
+ recently. To open an app, tap it. To remove a thumbnail from the list,
+ swipe it left or right. This button isn't supported for Android Wear.</td>
+ <td><div>Ctrl+O</div><div>⌘O</div></td>
+ </tr>
+ <tr>
+ <td>Menu</td>
+ <td>Type the keyboard shortcut to simulate the Menu button, for example,
+ to open the menu for the selected app.</td>
+ <td><div>Ctrl+M</div><div>⌘M</div></td>
+ </tr>
+ <tr>
+ <td>More<br><img src="{@docRoot}images/tools/e-imore.png"
+ style="vertical-align:sub;margin:0;height:9px" alt="More icon" /></td>
+ <td>Click to access other features and settings, described in the next
+ table.</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>Install an APK</td>
+ <td>Drag an APK file onto the emulator screen. An APK Installer dialog
+ appears. When the installation completes, you can view the app in your
+ apps list.The app didn’t install if a dialog appears that says “APK failed
+ to install.”</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>Add a file</td>
+ <td>Drag any file onto the emulator screen. It’s placed in the
+ <code>/sdcard/Download</code> directory. Navigate to the file using the
+ method for the API level. For example, for API 22, this is the navigation
+ path: <strong>Settings</strong> > <strong>Device: Storage & USB</strong>
+ > <strong>Internal Storage</strong> > <strong>Explore</strong>
+ (Virtual SD Card). </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>Toggle trackball mode</td>
+ <td></td>
+ <td>F6</td>
+ </tr>
+</table>
+
+<h2 id="extended">Working With the Extended Controls, Settings, and Help</h2>
+
+<p>The extended controls let you send data, change device properties, control
+apps, and more. To access the controls, select <strong>…</strong> in the
+emulator panel and then select the option you want in the left panel of the
+<em>Extended Controls</em> dialog.</p>
+
+<table border="0" style="clear:left;">
+ <tr>
+ <th scope="col">Feature</th>
+ <th scope="col">Description</th>
+ <th scope="col">Keyboard Shortcuts</th>
+ </tr>
+ <tr>
+ <td>Location</td>
+ <td>
+<p>The emulator lets you simulate “my location” information: the location where
+the emulated device is currently located. For example, if you click My Location
+<img src="{@docRoot}images/tools/e-ilocation.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="My Location icon" />
+ in Google Maps and then send a location, the map shows it.</p>
+ <p>To send a GPS location:</p>
+<ol>
+ <li> Select <strong>Decimal</strong> or <strong>Sexagesimal</strong>.</li>
+ <li> Specify the location.</li>
+
+<p>In decimal mode, enter a <strong>Latitude</strong> value in the range -90.0
+to +90.0 degrees and a <strong>Longitude</strong> value in the range -180.0 to
++180.0 degrees.</p>
+<p>In sexigesimal mode, enter a three-part <strong>Latitude</strong> value in
+the range -90 to +90 degrees, 0 to 59 minutes, and 0.0 to 60.0
+seconds. Enter a <strong>Longitude</strong> value in the range -180 to +180
+degrees, 0 to 59 minutes, and 0.0 to 60.0 seconds.</p>
+<p>For the latitude, - indicates south and + indicates north; for the longitude,
+- indicates west and + indicates east. The + is optional.</p>
+<p>Optionally specify an <strong>Altitude</strong> value in the range
+-1,000.0 to +10,000.0 meters.</p>
+
+ <li> Click <strong>Send</strong>.</li>
+</ol>
+<p>To use geographic data from a GPS exchange format (GPX) or Keyhole Markup
+Language (KML) file:</p>
+<ol>
+ <li> Click <strong>Load GPX/KML</strong>.</li>
+ <li> In the file dialog, select a file on your computer and click
+ <strong>Open</strong>.</li>
+ <li> Optionally select a <strong>Speed</strong>.</li>
+<p>The speed defaults to the <strong>Delay</strong> value (<strong>Speed
+1X</strong>). You can increase the speed by double (<strong>Speed</strong>
+<strong>2X</strong>), triple (<strong>Speed 3X</strong>), and so on.</p>
+
+ <li> Click Run <img src="{@docRoot}images/tools/e-irun.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="Run icon" />.</li>
+</ol>
+</td>
+ <td><div>Ctrl+Shift+L</div><div>⇧⌘L</div></td>
+ </tr>
+ <tr>
+ <td>Cellular</td>
+ <td><p>The emulator lets you simulate various network conditions. You can
+ approximate the network speed for different network protocols, or you can
+ specify <strong>Full</strong>, which transfers data as quickly as your
+ computer allows. Specifying a network protocol is always slower than
+ <strong>Full</strong>. You can also specify the voice and data network
+ status, such as roaming. The defaults are set in the AVD.</p>
+ <p>Select a <strong>Network type</strong>:</p>
+<ul>
+ <li> GSM - Global System for Mobile Communications</li>
+ <li> HSCSD - High-Speed Circuit-Switched Data</li>
+ <li> GPRS - Generic Packet Radio Service</li>
+ <li> EDGE - Enhanced Data rates for GSM Evolution</li>
+ <li> UMTS - Universal Mobile Telecommunications System</li>
+ <li> HSPDA - High-Speed Downlink Packet Access</li>
+ <li> Full (default)</li>
+</ul>
+<p>Select a <strong>Voice status</strong>, <strong>Data status</strong>, or
+both:</p>
+<ul>
+ <li> Home (default)</li>
+ <li> Roaming</li>
+ <li> Searching</li>
+ <li> Denied (emergency calls only)</li>
+ <li> Unregistered (off)</li>
+</ul>
+</td>
+ <td><div>Ctrl+Shift+C</div><div>⇧⌘C</td>
+ </tr>
+ <tr>
+ <td>Battery</td>
+ <td><p>You can simulate the battery properties of a device to see how your
+ app performs under different conditions. To select a <strong>Charge
+ level</strong>, use the slider control.</p>
+ <p>Select a <strong>Charger connection</strong> value:</p>
+<ul>
+ <li>None</li>
+ <li>AC charger</li>
+</ul>
+<p>Select a <strong>Battery health</strong> value:</p>
+<ul>
+ <li> Good (default)</li>
+ <li> Failed</li>
+ <li> Dead</li>
+ <li> Overvoltage</li>
+ <li> Overheated</li>
+ <li> Unknown</li>
+</ul>
+<p>Select a <strong>Battery status </strong>value:</p>
+<ul>
+ <li> Unknown</li>
+ <li> Charging (default)</li>
+ <li> Discharging</li>
+ <li> Not charging</li>
+ <li> Full</li>
+</ul>
+</td>
+ <td><div>Ctrl+Shift+B</div><div>⇧⌘B</div></td>
+ </tr>
+ <tr>
+ <td>Phone</td>
+ <td><p>The emulator lets you simulate incoming phone calls and text
+ messages. Note that the information flow is one way, from the control to
+ the emulator. For example, the control doesn’t change its state if the
+ emulator hangs up; you need to end the call in the control.</p>
+ <p>To initiate a call to the emulator:</p>
+<ol>
+ <li> Select or type a phone number in the <strong>From</strong> field.</li>
+ <li> Click <strong>Call Device</strong>.</li>
+ <li> Optionally click <strong>Hold Call</strong> to put the call on hold.</li>
+ <li> To end the call, click <strong>End Call</strong>.</li>
+</ol>
+<p>To send a text message to the emulator:</p>
+<ol>
+ <li> Select or type a phone number in the <strong>From</strong> field.</li>
+ <li> Type a message in the <strong>SMS message</strong> field.</li>
+ <li> Click <strong>Send Message</strong>.</li>
+</ol>
+</td>
+ <td><div>Ctrl+Shift+P</div><div>⇧⌘P</div></td>
+ </tr>
+ <tr>
+ <td>Directional Pad</td>
+ <td><p>If the AVD has the directional pad enabled in the hardware profile,
+ you can use the directional pad controls with the emulator. However, not
+ all devices can support the directional pad; for example, an Android watch.
+ The buttons simulate the following actions:</p>
+<img src="{@docRoot}images/tools/e-dpad.png"
+ style="vertical-align:sub;margin:0;width:244px" alt="Directional Pad Control" />
+</td>
+ <td><div>Ctrl+Shift+D</div><div>⇧⌘D</div></td>
+ </tr>
+ <tr>
+ <td>Fingerprint</td>
+ <td><p>This control can simulate 10 different fingerprint scans. You can
+ use it to test fingerprint integration in your app. This feature isn't
+ supported for Android Wear.</p>
+ <p>To simulate a fingerprint scan on the virtual device:</p>
+<ol>
+ <li> Prepare an app to receive a fingerprint.</li>
+ <li> Select a <strong>Fingerprint</strong> value.</li>
+ <li> Click <strong>Touch Sensor</strong>.</li>
+</ol>
+</td>
+ <td><div>Ctrl+Shift+F</div><div>⇧⌘F</div></td>
+ </tr>
+ <tr>
+ <td>Settings</td>
+ <td><p>You can specify the following settings:</p>
+<ul>
+ <li> <strong>Emulator window theme</strong> - Select Light or Dark.</li>
+ <li> <strong>Send keyboard shortcuts to</strong> - By default, some keyboard
+ combinations will trigger emulator control shortcuts. If you’re developing
+ an app that includes keyboard shortcuts, such as one targeted at
+ devices with Bluetooth keyboards, you can change this setting to send
+ <em>all</em> keyboard input to the virtual device, including input
+ that would be a shortcut in the emulator.</li>
+ <li> <strong>Screenshot save location</strong> - Click the folder icon to
+ specify a location to save screenshots of the emulator screen.</li>
+ <li> <strong>Use detected ADB location</strong> - If you're running the
+ emulator from Android Studio, you should select this setting (the default).
+ If you run the emulator from outside Android Studio and want it to use a
+ specific adb executable, deselect this option and specify the SDK Tools
+ location. If this setting is incorrect, features such as drag-and-drop app
+ install and file copy, and screenshot capture, won't work. </li>
+ <li> <strong>When to send crash reports</strong> - Select Always, Never, or
+ Ask. </li>
+</ul>
+</td>
+ <td>Ctrl+Shift+S<br>⇧⌘S</td>
+ </tr>
+ <tr>
+ <td>Help > Keyboard Shortcuts</td>
+ <td><p>See the keyboard shortcuts that the emulator accepts. For the
+ shortcuts to work, you need to:</p>
+<ul>
+ <li>Select <strong>Settings</strong> > <strong>Send keyboard shortcuts
+ to</strong> > <strong>Emulator controls (default)</strong>.</li>
+</ul>
+</td>
+ <td>F1<br>⌘/</td>
+ </tr>
+ <tr>
+ <td>Help > Emulator Help</td>
+ <td><p>To go to the online documentation for the emulator, click
+ <strong>Documentation</strong>.</p>
+ <p>To file a bug against the emulator, click <strong>File a Bug</strong>.
+ </p>
+ <p>To make suggestions, click <strong>Send Feedback</strong>.</p>
+ <p>All of these links require an internet connection and a browser.</p> </td>
+ <td>F1<br>⌘/</td>
+ </tr>
+ <tr>
+ <td>Help > About</td>
+ <td><p>See which adb port the emulator uses, as well as the Android and
+ emulator version numbers. Compare the latest available emulator version
+ with your version to determine if you have the latest software installed.
+ </p>
+ <p>The emulator serial number is <strong>emulator-<em></strong>adb_port</em>,
+ which you can specify as an adb command line option, for example.</p></td>
+ <td>F1<br>⌘/</td>
+ </tr>
+</table>
+
+
+
+
+
diff --git a/docs/html/tools/devices/managing-avds.jd b/docs/html/tools/devices/managing-avds.jd
index fb680aa..8ba554e 100644
--- a/docs/html/tools/devices/managing-avds.jd
+++ b/docs/html/tools/devices/managing-avds.jd
@@ -1,297 +1,680 @@
-page.title=Managing AVDs with AVD Manager
-parent.title=Managing Virtual Devices
-parent.link=index.html
+page.title=Managing AVDs with the AVD Manager
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
-
<ol>
- <li><a href="#createavd">Creating an AVD</a>
- <ol>
- <li><a href="#CreateDefinition">Creating a device definition</a></li>
- <li><a href="#hardwareopts">Hardware options</a></li>
- </ol>
+ <li><a href="#viewing">Viewing and Managing Your AVDs</a></li>
+ <li><a href="#createavd">Creating an AVD</a></li>
+ <li><a href="#createhp">Creating a Hardware Profile</a></li>
+ <li><a href="#workingavd">Working With Existing AVDs</a></li>
+ <li><a href="#workinghp">Working With Existing Hardware Profiles</a>
</li>
+ <li><a href="#emulator">Running and Stopping an Emulator, and
+ Clearing Data</li>
+ <li><a href="#importexporthp">Importing and Exporting Hardware
+ Profiles</li>
+ <li><a href="#hpproperties">Hardware Profile Properties</a></li>
+ <li><a href="#avdproperties">AVD Properties</a></li>
<li><a href="#skins">Creating Emulator Skins</a></li>
</ol>
+ <h2>Dependencies and prerequisites</h2>
+ <ul>
+ <li>Android Studio 2.0 or higher</li>
+ <li>SDK Tools 25.0.10 or higher</li>
+ <li>Active network connection for certain operations, such as downloading
+ system images</li>
+ <li>adb integration enabled through <strong>Tools</strong> >
+ <strong>Android</strong> >
+ <strong>Enable ADB Integration</strong></li>
+ </ul>
</div>
</div>
- <p>The AVD Manager is a tool you can use
- to create and manage Android virtual devices (AVDs), which define device configurations
- for the <a href="{@docRoot}tools/devices/emulator.html"
- >Android Emulator</a>.</p>
+ <p>An Android Virtual Device (AVD) definition lets you define the
+ characteristics of an Android phone, tablet, Android Wear, or Android TV
+ device that you want to simulate in the
+ <a href="{@docRoot}tools/devices/emulator.html">Android Emulator</a>.
+ The AVD Manager helps you easily create and manage AVDs. </p>
-<p>To launch the AVD Manager:</p>
+ <p>To effectively test your app, you should create an AVD that models each
+ device type that your app is designed to support. For example, we recommend
+ that you create an AVD for each API level that's equal to and higher than the
+ minimum version you've specified in your manifest
+ <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"
+ style="white-space: nowrap;"
+ >{@code <uses-sdk>}</a> tag.</p>
+
+ <p>An AVD contains a hardware profile, system image, skin, and other
+ properties.</p>
+
+ <p>The hardware profile defines the characteristics of a device as
+ shipped from the factory. The AVD Manager comes preloaded with certain
+ hardware profiles, such as Nexus phone devices, and you can define and import
+ hardware profiles as needed. You can override some of the settings in your
+ AVD, if needed.</p>
+
+ <p>The AVD Manager helps you choose a system image for your AVD by providing
+ recommendations. It also lets
+ you download system images, some with add-on libraries, like Google APIs,
+ which your app might require. x86 system images run the fastest in the
+ emulator. Android Wear and Android TV devices tend to run best (and have
+ the largest installed base) on recent releases, while users of Android phones
+ and tablets tend to use slightly older releases, as shown in the
+ <a href="{@docRoot}about/dashboards/index.html">API level
+ dashboards</a>.</p>
+
+ <p>An emulator skin specifies the appearance of a device. The AVD Manager
+ provides some predefined skins. You can also define your own, or use skins
+ provided by third parties.</p>
+
+ <p>Just as with a real device, for apps to use certains features defined in an
+ AVD, such as the camera, it must have the corresponding
+ <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><code><uses-feature></code></a>
+ setting in the app manifest.</p>
+
+<h2 id="viewing">Viewing and Managing Your AVDs</h2>
+
+<p>The AVD Manager lets you manage your AVDs all in one place.</p>
+
+<p>To run the AVD Manager:</p>
+
<ul>
- <li>In Android Studio, select <strong>Tools > Android > AVD Manager</strong>, or click
- the AVD Manager icon <img src="{@docRoot}images/tools/avd-manager-studio.png"
- style="vertical-align:bottom;margin:0;height:19px"> in the toolbar.</li>
-
- <li>Or, use the command line to navigate to your SDK's <code>tools/</code> directory and execute:
- <pre class="no-prettyprint classic">$ android avd</pre>
- </li>
+ <li> In Android Studio, select <strong>Tools</strong> >
+ <strong>Android</strong> > <strong>AVD Manager</strong>.</li>
+ <li> Click AVD Manager <img src="{@docRoot}images/tools/avd-manager-studio.png"
+ style="vertical-align:sub;margin:0;height:17px" alt="AVD Manager icon">
+ in the toolbar.</li>
</ul>
- <p>The AVD Manager main screen shows your current virtual devices, as shown in figure 1.</p>
+<p>The AVD Manager appears.</p>
+<img src="{@docRoot}images/tools/avd-main.png" alt="AVD Manager main window" />
- <img src="{@docRoot}images/studio-avdmgr-firstscreen.png" alt="">
- <p class="img-caption"><strong>Figure 1.</strong> The AVD Manager main screen shows your current
- virtual devices.</p>
+<p>It displays any AVDs you’ve already defined. When you first install
+Android Studio, it creates one AVD. If you defined AVDs for Android Emulator
+24.0.<em>x</em> or lower, you need to recreate them.</p>
+<p>From this page you can:</p>
-<p class="note"><strong>Note:</strong> If you launch the AVD Manager from the command line, the UI
-is different than how it appears in Android Studio, as documented here. Most of the same
-functionality is available, but the command-line version of the AVD Manager
-is currently not documented.</p>
+<ul>
+ <li> Define a new <a href="#createavd">AVD</a> or
+ <a href="#createhp">hardware profile</a>.</li>
+ <li> Edit an existing <a href="#workingavd">AVD</a> or
+ <a href="#workinghp">hardware profile</a>.</li>
+ <li> Delete an <a href="#workingavd">AVD</a> or
+ <a href="#workinghp">hardware profile</a>.</li>
+ <li> <a href="#importexporthp">Import or export</a> hardware profile
+ definitions.</li>
+ <li> <a href="#emulator">Run</a> an AVD to start the emulator.</li>
+ <li> <a href="#emulator">Stop</a> an emulator.</li>
+ <li> <a href="#emulator">Clear</a> data and start fresh, from the same state
+ as when you first ran the emulator.</li>
+ <li> <a href="#workingavd">Show</a> the associated AVD <code>.ini</code> and
+ <code>.img</code> files on disk.</li>
+ <li> <a href="#workingavd">View</a> AVD configuration details that you can
+ include in any bug
+ reports to the Android Studio team.</li>
+</ul>
<h2 id="createavd">Creating an AVD</h2>
- <p>You can create as many AVDs as you would like to use with the Android Emulator.
- To effectively test your app, you should create an AVD that models each device type for which
- you have designed your app to support. For instance, you should create an AVD for each
- API level equal to and higher than the minimum version you've specified in your manifest
- <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html" style="white-space: nowrap;"
- >{@code <uses-sdk>}</a> tag.</p>
+ <p>You can <a href="#newavd">create a new AVD</a> from the beginning, or
+ <a href="#copyavd">duplicate an AVD</a> and change some properties.</p>
- <p>To create an AVD based on an existing device definition:</p>
+ <p id="newavd">To create a new AVD:</p>
<ol>
- <li>From the main screen (figure 1), click <strong>Create Virtual Device</strong>.</li>
+ <li id="selecthardwarepage">From the
+ <a href="#viewing"><em>Your Virtual Devices</em></a> page of
+ the AVD Manager, click <strong>Create Virtual Device</strong>.</li>
- <li><p>In the Select Hardware window, select a device configuration, such as Nexus 6,
- then click <strong>Next</strong>.</p>
+ <p>Alternatively,
+ <a href="{@docRoot}training/basics/firstapp/running-app.html">run your
+ app</a> from within Android Studio. In the <em>Select Deployment Target</em>
+ dialog, click <strong>Create New Emulator</strong>.</p>
- <img src="{@docRoot}images/studio-avdmgr-selecthdwr.png" alt="">
- <p class="img-caption"><strong>Figure 2.</strong> The Select Hardware window.</p>
+ <p>The <em>Select Hardware</em> page appears.</p>
+ <img src="{@docRoot}images/tools/avd-hardwareprofile.png"
+ alt="Hardware Profile page of the AVD Manager">
+
+ <li>Select a hardware profile,
+ and then click <strong>Next</strong>.</li>
+
+ <p>If you don't see the hardware profile you want, you can
+ <a href="#createhp">create</a>
+ or <a href="#importexporthp">import</a> a hardware profile.</p>
+
+ <p id="systemimagepage">The <em>System Image</em> page appears.</p>
+ <img src="{@docRoot}images/tools/avd-systemimage.png"
+ alt="System Image page of the AVD Manager">
+
</li>
- <li>Select the desired system version for the AVD and click <strong>Next</strong>.
+ <li>Select the system image for a particular API level, and then click
+ <strong>Next</strong>.
</li>
- <li>Verify the configuration settings, then click <strong>Finish</strong>.
- <p>If necessary, click <strong>Show Advanced Settings</strong> to select a custom skin
- for the hardware profile and adjust other hardware settings.</p>
+ <p>The <strong>Recommended</strong> tab lists recommended system images. The
+ other tabs include a more complete list. The right pane describes the
+ selected system image. x86 images run the fastest in the emulator.</p>
+ <p>If you see <strong>Download</strong> next to the system image, you need
+ to click it to download the system image. You must be connected to the
+ internet to download it.</p>
+
+ <p id="verifyconfigpage">The <em>Verify Configuration</em> page appears.</p>
+ <img src="{@docRoot}images/tools/avd-verifyconfig.png"
+ alt="Verify Configuration page of the AVD Manager">
+
+ <li>Change <a href="#avdproperties">AVD properties</a> as needed,
+ and then click <strong>Finish</strong>.
+ <p>Click <strong>Show Advanced Settings</strong> to show more
+ settings, such as the skin.</p>
</li>
- </ol>
- <p>To launch the AVD in the Android Emulator, click the launch button
- <img src="{@docRoot}images/tools/as-avd-start.png"
- style="vertical-align:bottom;margin:0;height:19px">
- in the list of AVDs.</p>
+ <p>The new AVD appears in the <em>Your Virtual Devices</em> page or the
+ <em>Select Deployment Target</em> dialog.</p>
+</ol>
-<h3 id="CreateDefinition">Creating a device definition</h3>
+ <p id="copyavd">To create an AVD starting with a copy:</p>
-<p>In case the available device definitions do not match the device type you'd like to emulate,
-you can create a custom device definition for your AVD:</p>
+ <ol>
+ <li>From the
+ <a href="#viewing"><em>Your Virtual Devices</em></a> page of
+ the AVD Manager, right-click an AVD and select
+ <strong>Duplicate</strong>.</li>
+
+ <p>Or click Menu
+ <img src="{@docRoot}images/tools/studio-advmgr-actions-dropdown-icon.png"
+ style="vertical-align:sub;margin:0;height:17px">
+ and select <strong>Duplicate</strong>.</p>
+
+ <p>The <a href="#verifyconfigpage"><em>Verify Configuration</em></a>
+ page appears.</p>
+
+ <li>Click <strong>Change</strong> or <strong>Previous</strong> if you
+ need to make changes on the
+ <a href="#systemimagepage"><em>System Image</em></a> and
+ <a href="#hardwareprofilepage"><em>Hardware Profile</em></a> pages.</li>
+
+ <li>Make your changes, and then click <strong>Finish</strong>.</li>
+
+ <p>The AVD appears in the <em>Your Virtual Devices</em> page.
+
+</ol>
+
+
+<h2 id="createhp">Creating a Hardware Profile</h2>
+
+<p>The AVD Manager provides predefined hardware profiles for common devices so
+you can easily add them to your AVD definitions. If
+you need to define a different device, you can create a new hardware profile.
+You can <a href="#newhp">define a new hardware profile</a> from the beginning,
+or <a href="#copyavd">copy a hardware profile</a> as a start. The preloaded
+hardware profiles aren't editable.</p>
+
+<p id="newhp">To create a new hardware profile from the beginning:</p>
<ol>
- <li>From the main screen (figure 1), click <strong>Create Virtual Device</strong>.</li>
- <li>To begin you custom device by using an existing device profile as a template, select
- a device profile then click <strong>Clone Device</strong>.
- <p>Or, to start from scratch, click <strong>New Hardware Profile</strong>.</p>
- </li>
- <li>
-<p>The following Configure Hardware Profile window (figure 3) allows you to specify various
-configurations such as the screen size, memory options, input type, and sensors.</p>
+ <li>In the <a href="#selecthardwarepage"><em>Select Hardware</em></a>
+ page, click <strong>New Hardware Profile</strong>.</li>
- <p>When you're done configuring the device, click <strong>Finish</strong>.</p>
+ <li>In the <em>Configure Hardware Profile</em> page, change the
+ <a href="#hpproperties">hardware profile properties</a> as
+ needed.</li>
- <img src="{@docRoot}images/studio-avdmgr-confighardwareprof.png" alt="">
- <p class="img-caption"><strong>Figure 3.</strong> The Configure Hardware window when
- creating a custom device configuration.</p>
- </li>
- <li>Your custom device configuration is now available in the list of device definitions
- (shown after you click <strong>Create Virtual Device</strong>). To continue preparing an AVD
- with your custom device configuration, select the new configuration and follow the instructions
- above to create an AVD with an existing device definition (and select your new definition).</li>
+ <li>Click <strong>Finish</strong>.</li>
+ <p>Your new hardware profile appears in the <em>Select Hardware</em> page.
+ You can optionally <a href="#selecthardwarepage">create an AVD</a>
+ that uses the hardware profile
+ by clicking <strong>Next</strong>. Or, click <strong>Cancel</strong> to return
+ to the <em>Your Virtual Devices</em> page or <em>Select Deployment Target</em>
+ dialog.</p>
+ </ol>
- </ol>
+<p id="copyhp">To create a hardware profile starting with a copy:</p>
+
+ <ol>
+ <li>In the <a href="#selecthardwarepage"><em>Select Hardware</em></a>
+ page, select a hardware profile and click <strong>Clone Device</strong>.</li>
+
+ <p>Or right-click a hardware profile and select <strong>Clone</strong>.</li>
+
+ <li>In the <em>Configure Hardware Profile</em> page, change the
+ <a href="#hpproperties">hardware profile properties</a> as
+ needed.</li>
+
+ <li>Click <strong>Finish</strong>.</li>
+
+ <p>Your new hardware profile appears in the <em>Select Hardware</em> page.
+ You can optionally <a href="#selecthardwarepage">create an AVD</a>
+ that uses the hardware profile
+ by clicking <strong>Next</strong>. Or, click <strong>Cancel</strong> to return
+ to the <em>Your Virtual Devices</em> page or <em>Select Deployment Target</em>
+ dialog.</p>
+ </ol>
+<h2 id="workingavd">Working With Existing AVDs</h2>
-<h3 id="hardwareopts">Hardware options</h3>
+ <p>From the <a href="#viewing"><em>Your Virtual Devices</em></a> page, you can
+ perform the following operations on an existing AVD:</p>
+ <ul>
+ <li>To edit an AVD, click Edit
+ <img src="{@docRoot}images/tools/studio-advmgr-actions-edit-icon.png"
+ style="vertical-align:sub;margin:0;height:17px"> and
+ <a href="#copyavd">make your changes</a>.</li>
+ <li>To delete an AVD, right-click an AVD and select
+ <strong>Delete</strong>. Or click Menu
+ <img src="{@docRoot}images/tools/studio-advmgr-actions-dropdown-icon.png"
+ style="vertical-align:sub;margin:0;height:17px">
+ and select <strong>Delete</strong>.</li>
+ <li>To show the associated AVD <code>.ini</code> and
+ <code>.img</code> files on disk, right-click an AVD and select
+ <strong>Show on Disk</strong>. Or click Menu
+ <img src="{@docRoot}images/tools/studio-advmgr-actions-dropdown-icon.png"
+ style="vertical-align:sub;margin:0;height:17px">
+ and select <strong>Show on Disk</strong>.</li>
+ <li> To view AVD configuration details that you can
+ include in any bug reports to the Android Studio team, right-click an AVD and
+ select <strong>View Details</strong>. Or click Menu
+ <img src="{@docRoot}images/tools/studio-advmgr-actions-dropdown-icon.png"
+ style="vertical-align:sub;margin:0;height:17px">
+ and select <strong>View Details</strong>.</li>
+ </ul>
-<p>If you are creating a new AVD, you can specify the following hardware options for the AVD
-to emulate:</p>
- <table>
- <tr>
- <th>Characteristic</th>
+<h2 id="workinghp">Working With Existing Hardware Profiles</h2>
- <th>Description</th>
+<p>From the <a href="#selecthardwarepage"><em>Select Hardware</em></a> page,
+you can
+ perform the following operations on an existing hardware profile:</p>
+ <ul>
+ <li>To edit a hardware profile, select it and click
+ <strong>Edit Device</strong>. Or right-click a hardware profile and select
+ <strong>Edit</strong>. Next,
+ <a href="#copyhp">make your changes</a>.</li>
- <th>Property</th>
- </tr>
+ <li>To delete a hardware profile, right-click it and select
+ <strong>Delete</strong>. </li>
+ </ul>
+ <p>You can't edit or delete the predefined hardware profiles.</p>
- <tr>
- <td>Device ram size</td>
+<h2 id="emulator">Running and Stopping an Emulator, and Clearing Data</h2>
- <td>The amount of physical RAM on the device, in megabytes. Default value is "96".</td>
+ <p>From the <a href="#viewing"><em>Your Virtual Devices</em></a> page, you can
+ perform the following operations on an emulator:</p>
+ <ul>
+ <li>To run an emulator that uses an AVD, double-click the AVD. Or click Run
+ <img src="{@docRoot}images/tools/as-avd-start.png"
+ style="vertical-align:sub;margin:0;height:17px">.</li>
+ <li>To stop a running emulator, right-click an AVD and select
+ <strong>Stop</strong>. Or click Menu
+ <img src="{@docRoot}images/tools/studio-advmgr-actions-dropdown-icon.png"
+ style="vertical-align:sub;margin:0;height:17px">
+ and select <strong>Stop</strong>.</li>
+ <li>To clear the data for an emulator, and return it to the same state as when
+ it was first defined, right-click an AVD and select
+ <strong>Wipe Data</strong>. Or click Menu
+ <img src="{@docRoot}images/tools/studio-advmgr-actions-dropdown-icon.png"
+ style="vertical-align:sub;margin:0;height:17px">
+ and select <strong>Wipe Data</strong>.</li>
+ </ul>
- <td>hw.ramSize</td>
- </tr>
+<h2 id="importexporthp">Importing and Exporting Hardware Profiles</h2>
- <tr>
- <td>Touch-screen support</td>
+<p>From the <a href="#selecthardwarepage"><em>Select Hardware</em></a> page,
+you can import and export hardware profiles:</p>
+ <ul>
+ <li>To import a hardware profile, click
+ <strong>Import Hardware Profiles</strong> and select the XML file containing
+ the definition on your computer.</li>
- <td>Whether there is a touch screen or not on the device. Default value is "yes".</td>
+ <li>To export a hardware profile, right-click it and select
+ <strong>Export</strong>. Specify the location where you want to store the
+ XML file containing the definition.</i>
+ </ul>
- <td>hw.touchScreen</td>
- </tr>
+<h2 id="hpproperties">Hardware Profile Properties</h2>
- <tr>
- <td>Trackball support</td>
+<p>You can specify the following properties of hardware profiles in the
+<a href="#createhp"><em>Configure Hardware Profile</em></a> page. AVD
+configuration properties override hardware profile properties, and emulator
+properties that you set while the emulator is running override them both.</p>
- <td>Whether there is a trackball on the device. Default value is "yes".</td>
+<p>The predefined hardware profiles included with the AVD Manager aren't
+editable. However, you can copy them and edit the copies.</p>
- <td>hw.trackBall</td>
- </tr>
- <tr>
- <td>Keyboard support</td>
+<table>
+ <tr>
+ <th scope="col">Hardware Profile Property</th>
+ <th scope="col">Description</th>
+ </tr>
+ <tr>
+ <td>Device Name</td>
+ <td>Name of the hardware profile. The name can contain uppercase or
+ lowercase letters,
+ numbers from 0 to 9, periods (.), underscores (_), and parentheses ( () ).
+ The name of the file storing the hardware profile is derived from the
+ hardware profile name.
+ </td>
+ </tr>
+ <tr>
+ <td>Device Type</td>
+ <td>Select one of the following:
+<ul>
+ <li> Phone/Tablet
+ <li> Android Wear
+ <li> Android TV
+</ul>
+</td>
+ </tr>
- <td>Whether the device has a QWERTY keyboard. Default value is "yes".</td>
+ <tr>
+ <td>Screen Size </td>
+ <td>The physical size of the screen, in inches, measured at the diagonal.
+ If the size is larger than your computer screen, it’s reduced in size at
+ launch.</td>
+ </tr>
+ <tr>
+ <td>Screen Resolution</td>
+ <td>Type a width and height in pixels to specify the total number of pixels
+ on the simulated screen.</td>
- <td>hw.keyboard</td>
- </tr>
+ </tr>
+ <tr>
+ <td>Round</td>
+ <td>Select this option if the device has a round screen, such as an
+ Android Wear device. </td>
+ </tr>
+ <tr>
+ <td>Memory: RAM</td>
+ <td>Type a RAM size for the device and select the units, one of B (byte),
+ KB (kilobyte), MB (megabyte), GB (gigabyte), or TB (terabyte).</td>
+ </tr>
- <tr>
- <td>DPad support</td>
+ <tr>
+ <td>Input: Has Hardware Buttons (Back/Home/Menu)</td>
+ <td>Select this option if your device has hardware navigation buttons.
+ Deselect it if these buttons are implemented in software only. If you
+ select this option, the buttons won’t appear on the screen. You can use the
+ emulator side panel to “press” the buttons, in either case.</td>
+ </tr>
+ <tr>
+ <td>Input: Has Hardware Keyboard</td>
+ <td>Select this option if your device has a hardware keyboard. Deselect it
+ if it doesn’t. If you select this option, a keyboard won’t appear on the
+ screen. You can use your computer keyboard to send keystrokes to the
+ emulator, in either case.</td>
+ </tr>
+ <tr>
+ <td>Navigation Style</td>
+ <td><p>Select one of the following:</p>
+<ul>
+ <li> None - No hardware controls. Navigation is through the software.
+ <li> D-pad - Directional Pad support.
+ <li> Trackball
+ <li> Wheel
+</ul>
+ <p>These options are for actual hardware controls on the device itself.
+ However,
+ the events sent to the device by an external controller are the same.</p>
+</td>
+ </tr>
+ <tr>
+ <td>Supported Device States</td>
+ <td><p>Select one or both options:</p>
+<ul>
+ <li> Portrait - Oriented taller than wide.
+ <li> Landscape - Oriented wider than tall.
+</ul>
+<p>If you select both, you can switch between orientations in the emulator.
+You must select at least one option to continue.</p></td>
+ </tr>
+ <tr>
+ <td>Cameras</td>
+ <td><p>Select one or both options:</p>
+<ul>
+ <li> Back-Facing Camera - The lens faces away from the user.
+ <li> Front-Facing Camera - The lens faces toward the user.
+</ul>
+<p>Later, you can use a webcam or a photo provided by the emulator to simulate
+taking a photo with the camera.</td>
+ </tr>
- <td>Whether the device has DPad keys. Default value is "yes".</td>
+ <tr>
+ <td>Sensors: Accelerometer</td>
+ <td>Select if the device has hardware that helps the device determine
+ its orientation.</td>
+ </tr>
+ <tr>
+ <td>Sensors: Gyroscope</td>
+ <td>Select if the device has hardware that detects rotation or twist.
+ In combination with an
+ accelerometer, it can provide smoother orientation detection and support
+ a six-axis orientation system.</td>
+ </tr>
+ <tr>
+ <td>Sensors: GPS</td>
+ <td>Select if the device has hardware that supports the Global Positioning
+ System (GPS)
+ satellite-based navigation system.</td>
+ </tr>
+ <tr>
+ <td>Sensors: Proximity Sensor</td>
+ <td>Select if the device has hardware that detects if the device is close
+ to your face during a
+ phone call to disable input from the screen.</td>
+ </tr>
+ <tr>
+ <td>Default Skin</td>
+ <td>Select a skin that controls what the device looks like when displayed
+ in the
+ emulator. Remember that specifying a screen size that's too small for the
+ resolution can mean that the screen is cut off, so you can't see the whole
+ screen. See
+ <a href="{@docRoot}tools/devices/managing-avds.html#skins">Creating Emulator Skins</a>
+ for more information.</td>
+ </tr>
+</table>
- <td>hw.dPad</td>
- </tr>
+<h2 id="avdproperties">AVD Properties</h2>
- <tr>
- <td>GSM modem support</td>
+<p>You can specify the following properties for AVD configurations
+in the <a href="#verifyconfigpage"><em>Verify Configuration</em></a> page.
+The AVD configuration specifies the interaction between the development
+computer and the emulator, as well as properties you want to override in the
+hardware profile.</p>
- <td>Whether there is a GSM modem in the device. Default value is "yes".</td>
+<p>AVD configuration properties override hardware profile properties,
+and emulator
+properties that you set while the emulator is running override them both.</p>
- <td>hw.gsmModem</td>
- </tr>
+<table>
+ <tr>
+ <th scope="col">AVD Property</th>
+ <th scope="col">Description</th>
+ </tr>
+ <tr>
+ <td>AVD Name</td>
+ <td>Name of the AVD. The name can contain uppercase or
+ lowercase letters,
+ numbers from 0 to 9, periods (.), underscores (_), and parentheses ( () ).
+ The name of the file storing the AVD configuration is derived from the AVD
+ name.
+ </td>
+ </tr>
+ <tr>
+ <td>AVD ID (Advanced)</td>
+ <td>The AVD filename is derived from the ID, and you can use the ID to
+ refer to the AVD from the command line.</td>
+ </tr>
+ <tr>
+ <td>Hardware Profile</td>
+ <td>Click <strong>Change</strong> to select a different hardware profile in
+ the <a href="#selecthardwarepage"><em>Select Hardware</em></a> page.</td>
+ </tr>
+ <tr>
+ <td>System Image</td>
+ <td>Click <strong>Change</strong> to select a different system image in the
+ <a href="#systemimagepage"><em>System Image</em></a> page.
+ An active internet connection is required to download a new image. </td>
+ </tr>
- <tr>
- <td>Camera support</td>
+ <tr>
+ <td>Startup: Scale </td>
+ <td>Select the initial size you want to use when the emulator launches.
+ This size might be adjusted to a smaller size if it’s larger than the
+ computer screen. The default is Auto (automatic).</td>
+ </tr>
+ <tr>
+ <td>Startup: Orientation</td>
+ <td><p>Select one option for the initial emulator orientation:</p>
+<ul>
+ <li> Portrait - Oriented taller than wide.
+ <li> Landscape - Oriented wider than tall.
+</ul>
+<p>An option is enabled only if it’s selected in the hardware profile. When
+running the AVD in the emulator, you can change the orientation if portrait and
+landscape are supported in the hardware profile.</p></td>
+ </tr>
+ <tr>
+ <td>Camera (Advanced)</td>
+ <td><p>Select one or both options:</p>
+<ul>
+ <li> Front - The lens faces away from the user.
+ <li> Back - The lens faces toward the user.
+</ul>
+<p>This option is available only if it's selected in the hardware profile; it's
+not available for Android Wear and Android TV.</p></td>
+ </tr>
- <td>Whether the device has a camera. Default value is "no".</td>
+ <tr>
+ <td>Network: Speed (Advanced)</td>
+ <td><p>Select a network protocol to determine the speed of data transfer:
+ </p>
+ <ul>
+ <li>GSM - Global System for Mobile Communications</li>
+<li>HSCSD - High-Speed Circuit-Switched Data</li>
+<li>GPRS - Generic Packet Radio Service</li>
+<li>EDGE - Enhanced Data rates for GSM Evolution</li>
+<li>UMTS - Universal Mobile Telecommunications System</li>
+<li>HSPDA - High-Speed Downlink Packet Access</li>
+<li>Full (default) - Transfer data as quickly as your computer allows.</li>
+</ul>
+</td>
+ </tr>
+ <tr>
+ <td>Network: Latency (Advanced)</td>
+ <td>Select a network protocol to set how much time (delay) it takes for the
+ protocol to transfer a data packet from one point to another point.</td>
+ </tr>
- <td>hw.camera</td>
- </tr>
+ <tr>
+ <td>Emulated Performance: Graphics</td>
+ <td><p>Select how graphics are rendered in the emulator:</p>
+ <ul>
+ <li>Hardware - Use your computer graphics card for faster rendering.</li>
+ <li>Software - Emulate the graphics in software, which is useful if you're
+ having a problem with rendering in your graphics card.</li>
+ <li>Auto - Let the emulator decide the best option based on your graphics
+ card.</li>
+ </td>
+ </tr>
+ <tr>
+ <td>Multi-Core CPU (Advanced)</td>
+ <td>Select the number of processor cores on your computer that you’d like
+ to use for the emulator. Using more processor cores speeds up the emulator.
+ </td>
+ </tr>
- <tr>
- <td>Maximum horizontal camera pixels</td>
+ <tr>
+ <td>Memory and Storage: RAM</td>
+ <td>The amount of RAM on the device. This value is set by the hardware
+ manufacturer, but you can override it, if needed, such as for faster
+ emulator operation. Increasing the size uses more resources on your
+ computer. Type a RAM size and select the
+ units, one of B (byte), KB (kilobyte), MB (megabyte), GB (gigabyte), or
+ TB (terabyte).</td>
+ </tr>
+ <tr>
+ <td>Memory and Storage: VM Heap</td>
+ <td>The VM heap size. This value is set by the hardware
+ manufacturer, but you can override it, if needed. Type a heap size and
+ select the
+ units, one of B (byte), KB (kilobyte), MB (megabyte), GB (gigabyte), or
+ TB (terabyte). For more information on Android VMs, see
+ <a href="{@docRoot}tools/help/am-memory.html#vm">Memory Management for
+ Different Virtual Machines</a>.</td>
+ </tr>
+ <tr>
+ <td>Memory and Storage: Internal Storage</td>
+ <td>The amount of nonremovable memory space available on the device. This
+ value is set by the hardware
+ manufacturer, but you can override it, if needed. Type a size and select the
+ units, one of B (byte), KB (kilobyte), MB (megabyte), GB (gigabyte), or
+ TB (terabyte).</td>
+ </tr>
+ <tr>
+ <td>Memory and Storage: SD Card</td>
+ <td>The amount of removable memory space available to store data on the
+ device. To use a virtual SD card managed by Android Studio, select
+ <strong>Studio</strong>, type a size, and select the
+ units, one of B (byte), KB (kilobyte), MB (megabyte), GB (gigabyte), or
+ TB (terabyte). A minimum of 100 MB is recommended to use the camera. To
+ manage the space in a file, select <strong>External File</strong> and
+ click <strong>...</strong> to specify the file and location. For more
+ information, see <a href="{@docRoot}tools/help/mksdcard.html">mksdcard</a>.
+ </td>
+ </tr>
- <td>Default value is "640".</td>
-
- <td>hw.camera.maxHorizontalPixels</td>
- </tr>
-
- <tr>
- <td>Maximum vertical camera pixels</td>
-
- <td>Default value is "480".</td>
-
- <td>hw.camera.maxVerticalPixels</td>
- </tr>
-
- <tr>
- <td>GPS support</td>
-
- <td>Whether there is a GPS in the device. Default value is "yes".</td>
-
- <td>hw.gps</td>
- </tr>
-
- <tr>
- <td>Battery support</td>
-
- <td>Whether the device can run on a battery. Default value is "yes".</td>
-
- <td>hw.battery</td>
- </tr>
-
- <tr>
- <td>Accelerometer</td>
-
- <td>Whether there is an accelerometer in the device. Default value is "yes".</td>
-
- <td>hw.accelerometer</td>
- </tr>
-
- <tr>
- <td>Audio recording support</td>
-
- <td>Whether the device can record audio. Default value is "yes".</td>
-
- <td>hw.audioInput</td>
- </tr>
-
- <tr>
- <td>Audio playback support</td>
-
- <td>Whether the device can play audio. Default value is "yes".</td>
-
- <td>hw.audioOutput</td>
- </tr>
-
- <tr>
- <td>SD Card support</td>
-
- <td>Whether the device supports insertion/removal of virtual SD Cards. Default value is
- "yes".</td>
-
- <td>hw.sdCard</td>
- </tr>
-
- <tr>
- <td>Cache partition support</td>
-
- <td>Whether we use a /cache partition on the device. Default value is "yes".</td>
-
- <td>disk.cachePartition</td>
- </tr>
-
- <tr>
- <td>Cache partition size</td>
-
- <td>Default value is "66MB".</td>
-
- <td>disk.cachePartition.size</td>
- </tr>
-
- <tr>
- <td>Abstracted LCD density</td>
-
- <td>Sets the generalized density characteristic used by the AVD's screen. Default value is
- "160".</td>
-
- <td>hw.lcd.density</td>
- </tr>
- </table>
+ <tr>
+ <td>Device Frame: Enable Device Frame</td>
+ <td>Select to enable a frame around the emulator window that mimics the
+ look of a real device.</td>
+ </tr>
+ <tr>
+ <td>Custom Skin Definition (Advanced)</td>
+ <td>Select a skin that controls what the device looks like when displayed in
+ the emulator. Remember that specifying a screen size that's too small for
+ the resolution can mean that the screen is cut off, so you can't see the
+ whole screen. See
+ <a href="{@docRoot}tools/devices/managing-avds.html#skins">Creating Emulator Skins</a>
+ for more information.</td>
+ </tr>
+ <tr>
+ <td>Keyboard: Enable Keyboard Input (Advanced)</td>
+ <td>Select this option if you want to use your hardware keyboard to interact
+ with the emulator. It's disabled for Android Wear and Android TV.</td>
+ </tr>
+</table>
<h2 id="skins">Creating Emulator Skins</h2>
-<p>An Android emulator skin is a collection of files that define the visual and control elements of
-an emulator display. If the skin definitions available in the AVD settings don't meet your needs,
-you can create your own custom skin definition, then apply it to your AVD from the
-advanced settings on the Verify Configuration screen.</p>
+<p>An Android emulator skin is a collection of files that define the visual
+and control elements of
+an emulator display. If the skin definitions available in the AVD settings
+don't meet your requirements,
+you can create your own custom skin definition, and then apply it to your AVD.
+</p>
<p>Each emulator skin contains:</p>
<ul>
<li>A <code>hardware.ini</code> file</li>
- <li>Layout files for supported orientations (landscape, portrait) and physical configuration</li>
- <li>Image files for display elements, such as background, keys and buttons</li>
+ <li>Layout files for supported orientations (landscape, portrait) and
+ physical configuration</li>
+ <li>Image files for display elements, such as background, keys and
+ buttons</li>
</ul>
<p>To create and use a custom skin:</p>
<ol>
- <li>Create a new directory where you will save your skin configuration files. </li>
+ <li>Create a new directory where you will save your skin configuration
+ files. </li>
<li>Define the visual appearance of the skin in a text file named
- <code>layout</code>. This file defines many characteristics of the skin, such as the
+ <code>layout</code>. This file defines many characteristics of the skin,
+ such as the
size and image assets for specific buttons. For example:
<pre class="no-prettyprint">
parts {
@@ -322,14 +705,16 @@
</pre></li>
<li>Add the bitmap files of the device images in the same directory.</li>
- <li>Specify additional hardware-specific device configurations an <code>hardware.ini</code>
+ <li>Specify additional hardware-specific device configurations in a
+ <code>hardware.ini</code>
file for the device settings, such as <code>hw.keyboard</code> and
<code>hw.lcd.density</code>.</li>
- <li>Archive the files in the skin folder and select the archive file as a custom skin. </li>
+ <li>Archive the files in the skin folder and select the archive file as a
+ custom skin.</li>
</ol>
<p>For more detailed information about creating emulator skins, see the
-<a href="https://android.googlesource.com/platform/external/qemu.git/+/master/docs/ANDROID-SKIN-FILES.TXT"
+<a href="https://android.googlesource.com/platform/external/qemu/+/emu-master-dev/docs/ANDROID-SKIN-FILES.TXT"
>Android Emulator Skin File Specification</a> in the tools source code.</p>
diff --git a/docs/html/tools/help/app-link-indexing.jd b/docs/html/tools/help/app-link-indexing.jd
index 611373a..5b76059 100644
--- a/docs/html/tools/help/app-link-indexing.jd
+++ b/docs/html/tools/help/app-link-indexing.jd
@@ -1,4 +1,4 @@
-page.title=Deep Link and App Indexing API Support in Android Studio
+page.title=Supporting URLs and App Indexing in Android Studio
parent.title=Tools
parent.link=index.html
page.tags=app indexing
@@ -9,11 +9,13 @@
<h2>In this document</h2>
<ol>
<li><a href="#workflow">Typical Workflow</a></li>
- <li><a href="#intent">Adding an Intent Filter for Deep Linking and Google Search</a></li>
+ <li><a href="#intent">Adding an Intent Filter for URL Support and Google Search</a></li>
<li><a href="#indexing">Adding App Indexing API Skeleton Code to an Activity</a></li>
- <li><a href="#testintent">Testing a Deep Link</a></li>
+ <li><a href="#testintent">Testing a URL</a></li>
<li><a href="#testindexing">Viewing App Indexing API Messages in the logcat Monitor</a></li>
<li><a href="#lint">Configuring Lint</a></li>
+ <li><a href="#appindexingtest">Performing a Google App Indexing Test</a></li>
+
</ol>
<h2>See also</h2>
@@ -48,15 +50,16 @@
</div>
</div>
-<p>Android Studio helps you add deep links, app indexing, and search functionality to your apps.
+<p>Android Studio helps you add support for URLs, app indexing, and search
+functionality to your apps.
These features can help to drive more traffic to your
app, discover which app content is used most, make it easier for users to find content in an
installed app, and attract new users.</p>
<h2 id="workflow">Typical Workflow</h2>
-<p>To use Android Studio to add deep link, app indexing, and search features to your app, follow
- these basic steps:</p>
+<p>To use Android Studio to add support for URL, app indexing, and search
+features to your app:</p>
<ol>
<li>Add intent filters and code to handle incoming intents.</li>
@@ -64,23 +67,25 @@
<li>Add App Indexing API code.</li>
</ol>
-<p>Intent filters and the App Indexing API are ways to implement deep links and app indexing, but
+<p>Intent filters and the App Indexing API are ways to implement URL support
+and app indexing, but
there are other possible implementations as well. See
<a href="https://developers.google.com/app-indexing/reference/deeplinks"
class="external-link">Alternate Android Indexing Methods</a>
for more information.</p>
-<h3 id="aboutintent">Intent filters for deep links</h3>
+<h3 id="aboutintent">Intent filters for URLs</h3>
<p>Android Studio can create a basic intent filter in your manifest that you can customize to
- define deep link URLs for your app. You can then write Java code in an activity to handle the
+ define URLs for your app. You can then write Java code in an activity to handle the
intent. This implementation lets users directly open the specified app activity by
- clicking a deep link. Users can see the deep links in google.com in a browser, in the
+ clicking a URL. Users can see the URLs in google.com in a browser, in the
Google Search app, and in Google Now on Tap. </p>
-<h3 id="aboutassociation">Website association with deep links</h3>
+<h3 id="aboutassociation">Website association with URLs</h3>
-<p>After setting up deep links for your app, you can associate your website with your app by using
+<p>After setting up URL support for your app, you can associate your website
+with your app by using
the Google Search Console and Google Play Developer Console. Afterward, Google indexes your app
for URLs defined in
your intent filters and begins to include them in search results. In addition, you can optionally
@@ -91,11 +96,11 @@
<p>As an alternative to associating your app with a website,
for Android 6.0 (API level 23) and higher, you can add
<a href="{@docRoot}training/app-links/index.html"
- >default handlers and verification for deep links</a>
+ >default handlers and verification for URLs</a>
instead.</p>
-<p>Chrome displaying google.com serves search results with deep links that are accessible to both
- signed-in users and those who aren't. Google Search app users must be signed in to see deep links
+<p>Chrome displaying google.com serves search results with URLs that are accessible to both
+ signed-in users and those who aren't. Google Search app users must be signed in to see URLs
in their search results. </p>
<h3 id="aboutapi">App Indexing API code in activities</h3>
@@ -108,24 +113,27 @@
class="external-link">Googlebot</a>
can’t get content from your app.</p>
-<h3 id="abouttest">Deep link and App Indexing API testing</h3>
+<h3 id="abouttest">URL support and App Indexing API testing</h3>
<p>Android Studio helps you test your code with the following features:</p>
<ul>
-<li>Deep link testing helps you verify that a specified deep link can launch an app. </li>
+<li>URL support testing helps you verify that a specified URL can launch an app.
+</li>
<li>The logcat Monitor helps you test App Indexing API calls in an activity. </li>
-<li>The Android Lint tool has warnings for certain issues involving deep links and the App Indexing
+<li>The Android Lint tool has warnings for certain issues involving URL support
+and the App Indexing
API. These warnings and errors appear in the Code Editor and in Lint inspection results.</li>
+ <li>A Google App Indexing test checks whether Google can index a URL by
+ either crawling your app page or using the App Indexing API.</li>
</ul>
-<p>The details for implementing deep links and app indexing are described next.
+<p>The details for implementing URL support and app indexing are described next.
-<h2 id="intent">Adding an Intent Filter for Deep Linking and Google Search</h2>
+<h2 id="intent">Adding an Intent Filter for URL Support and Google Search</h2>
-<p>To use Android Studio features to add an intent filter defining a deep link, follow these
- steps:</p>
+<p>To use Android Studio features to add an intent filter defining a URL:</p>
<ol>
<li>In the <a href="{@docRoot}sdk/installing/create-project.html#ProjectView">Android view</a>
@@ -138,11 +146,11 @@
style="vertical-align:sub;margin:0;height:17px" alt="Lightbulb icon" /> appears. Click
<img src="{@docRoot}images/tools/ai-ilightbulb.png"
style="vertical-align:sub;margin:0;height:17px" alt="Lightbulb icon" />
- and select <strong>Create Deep Link</strong>.</li>
+ and select <strong>Create URL</strong>.</li>
<li>Right-click in an <code><activity></code> element and select <strong>Generate</strong>
- > <strong>Deep Link</strong>.</li>
+ > <strong>URL</strong>.</li>
<li>Place your cursor in an activity, and then select <strong>Code</strong> >
- <strong>Generate</strong> > <strong>Deep Link</strong>.</li>
+ <strong>Generate</strong> > <strong>URL</strong>.</li>
</ul>
<p>The Code Editor adds skeleton code using the
@@ -154,7 +162,7 @@
<p>The Code Editor adds an intent filter similar to the following:</p>
<pre>
<!-- ATTENTION: This intent was auto-generated. Follow instructions at
- https://g.co/AppIndexing/AndroidStudio to publish your Android app deep links. -->
+ https://g.co/AppIndexing/AndroidStudio to publish your URLs. -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -177,19 +185,20 @@
<p>We recommend that you define a <code><data></code> element that supports URLs that you’ll
add in the future. In the previous sample code, for example, Google will index any URLs starting
- with <code>www.example.com/gizmos</code>. Also, remember to
- include a deep link for your app home screen so it’s included in search results. </p>
+ with <code>http://www.example.com/gizmos</code>. Also, remember to
+ include a URL for your app home screen so it’s included in search results. </p>
-<p>Deep link URLs can be the same as the URLs of the comparable pages on your website.</p>
+<p>The URLs you specify in your intent filters can be the same as the URLs of
+the comparable pages on your website.</p>
<li>In the corresponding activity,
<a href="{@docRoot}training/app-indexing/deep-linking.html#handling-intents">add Java code</a>
to read data from the intent filter and direct the app to respond accordingly. </li>
-<li><a href="#testintent">Test your deep link</a>.</li>
+<li><a href="#testintent">Test your URL</a>.</li>
</ol>
-<p>To support Google Search for your deep links, follow these steps:</p>
+<p>To support Google Search for your URLs:</p>
<ol>
<li><a href="https://developers.google.com/app-indexing/android/app#declare-a-website-association"
class="external-link">Define an association</a>
@@ -198,7 +207,7 @@
<a href="{@docRoot}training/app-links/index.html">link default handling and verification</a>.</p>
<li>Optionally
<a href="https://developers.google.com/app-indexing/android/app#create-the-noindexxml-file"
- class="external-link">exclude app URLs</a>
+ class="external-link">exclude certain URLs</a>
from the Google index.</li>
<li>Optionally <a href="#indexing">add App Indexing API code</a> to support additional search
features.</li>
@@ -207,27 +216,28 @@
<p>To test and debug your links, you can use the following Android Studio features:</p>
<ul>
-<li><a href="#testintent">Launch your deep link</a> in Android Studio to test that it works.</li>
+<li><a href="#testintent">Launch your URL</a> in Android Studio to test that it works.</li>
<li><a href="#lint">Enable the following Android Lint categories</a>:</li>
<ul>
-<li><strong>Missing Support for Google App Indexing</strong></li>
-<li><strong>Incorrect Usage of App Link for Google App Indexing</strong></li>
+<li><strong>Missing support for Google App Indexing</strong></li>
+<li><strong>URL not supported by app for Google App Indexing</strong></li>
</ul>
+<li><a href="#appindexingtest">Perform a Google App Indexing Test</a>.</li>
</ul>
<p>In addition, you can
<a href="https://developers.google.com/app-indexing/android/test#preview-your-apk-on-search-console"
class="external-link">preview your APK in the Google Search Console</a>
- to test your deep links, whether the app is associated with a website or not. </p>
+ to test your URLs, whether the app is associated with a website or not. </p>
<h2 id="indexing">Adding App Indexing API Skeleton Code to an Activity</h2>
-<p>After adding deep links, you can add App Indexing API code to an activity to support additional
- search features. </p>
+<p>After adding URL support to your app, you can add App Indexing API code to
+an activity to support additional search features. </p>
-<p>To add App Indexing API code to an activity, follow these steps:</p>
+<p>To add App Indexing API code to an activity:</p>
<ol>
<li>In <a href="{@docRoot}sdk/installing/create-project.html#ProjectView">Android view</a>
in the <em>Project</em> window, double-click the activity Java file to open it in the
@@ -297,9 +307,9 @@
// this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
- Uri.parse("http://host/path"),
- // TODO: Make sure this auto-generated app deep link URI is correct.
- Uri.parse("android-app://com.example/http/host/path")
+ Uri.parse("http://www.example.com/gizmos"),
+ // TODO: Make sure this auto-generated app URL is correct.
+ Uri.parse("android-app://com.example/http/www.example.com/gizmos")
);
AppIndex.AppIndexApi.start(client, viewAction);
}
@@ -317,9 +327,9 @@
// this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
- Uri.parse("http://host/path"),
- // TODO: Make sure this auto-generated app deep link URI is correct.
- Uri.parse("android-app://com.example/http/host/path")
+ Uri.parse("http://www.example.com/gizmos"),
+ // TODO: Make sure this auto-generated app URL is correct.
+ Uri.parse("android-app://com.example/http/www.example.com/gizmos")
);
AppIndex.AppIndexApi.end(client, viewAction);
client.disconnect();
@@ -363,7 +373,9 @@
<ul>
<li><a href="#testindexing">Examine logcat Monitor Messages</a>.</li>
<li><a href="#lint">Enable the following Android Lint category</a>:
- <strong>Missing Support for Google App Indexing API</strong></li>
+ <strong>Missing support for Google App Indexing API</strong></li>
+
+<li><a href="#appindexingtest">Perform a Google App Indexing Test</a>.</li>
</ul>
<p>In addition, you can
@@ -371,12 +383,12 @@
class="external-link">preview your APK in the Google Search Console</a>.</p>
-<h2 id="testintent">Testing a Deep Link</h2>
+<h2 id="testintent">Testing a URL</h2>
-<p>When you run your app from Android Studio, you can specify a deep link to launch so you can
+<p>When you run your app from Android Studio, you can specify a URL to launch so you can
test it.</p>
-<p>To launch a deep link from Android Studio, follow these steps:</p>
+<p>To launch a URL from Android Studio:</p>
<ol>
<li>In Android Studio, open your project in
<a href="{@docRoot}sdk/installing/create-project.html#ProjectView">Android view</a>.</li>
@@ -385,14 +397,14 @@
<li>In the <em>Run/Debug Configurations</em> dialog, beneath <strong>Android Application,</strong>
select the module you want to test.</li>
<li>Select the <strong>General</strong> tab. </li>
-<li>In the <strong>Launch</strong> field, select <strong>Deep Link</strong>. </li>
-<li>In the <strong>Deep Link</strong> field, click <strong>…</strong> to select from a list of
- defined deep links.</li>
+<li>In the <strong>Launch</strong> field, select <strong>URL</strong>. </li>
+<li>In the <strong>URL</strong> field, click <strong>…</strong> to select from a list of
+ defined URLs.</li>
<p>Or type the URL you want to test, for example, <code>http://example.com/gizmos</code>. </p>
<li>Click <strong>OK</strong>.</li>
<li>Select <strong>Run</strong> > <strong>Run app</strong> or <strong>Debug app</strong>.</li>
-<li>If the <em>Device Chooser</em> dialog appears, select a connected device or an
+<li>If the <em>Select Deployment Target</em> dialog appears, select a connected device or an
emulator, and click <strong>OK</strong>.</li>
<p>If the link is successful, the app launches in the device or emulator, and displays the app at
@@ -411,12 +423,12 @@
<p>The logcat Monitor can display app indexing log messages to determine if your App Indexing API
code is pushing the correct data to the cloud. For example, you can check the app title and the
- URL. The logcat Monitor is part of Android Monitor in Android Studio. </p>
+ URL. The logcat Monitor is part of Android Monitor in Android Studio.</p>
-<p>Follow these steps:</p>
+<p>To view App Indexing API messages in the logcat Monitor:</p>
<ol>
-<li>Run your app in Android Studio so it <a href="#testintent">launches a deep link</a>.</li>
-<li><a href="{@docRoot}tools/help/android-monitor.html#displaying">Display Android Monitor</a>
+<li>Run your app in Android Studio so it <a href="#testintent">launches a URL</a>.</li>
+<li><a href="{@docRoot}tools/help/am-logcat.html#running">Display Android Monitor</a>
and click the <strong>logcat</strong> tab.</li>
<li><a href="{@docRoot}tools/help/am-logcat.html#level">Set the log level</a> to
<strong>Verbose</strong>.</li>
@@ -445,10 +457,10 @@
<h2 id="lint">Configuring Lint</h2>
-<p>You can use the Android Studio built-in Lint tool to check whether you have valid deep links
+<p>You can use the Android Studio built-in Lint tool to check whether you have valid URLs
defined in the manifest and have implemented the App Indexing API correctly in activities.</p>
-<p>You can view deep link and app indexing warnings and errors in two ways: </p>
+<p>You can view URL and app indexing warnings and errors in two ways: </p>
<ul>
<li>As pop-up text in the Code Editor. When Lint finds a problem, it highlights the problematic
code in yellow, or underlines the code in red for more serious issues.</li>
@@ -458,7 +470,7 @@
-<p>To set default Lint checks for deep links and the App Indexing API, follow these steps:</p>
+<p>To set default Lint checks for URLs and the App Indexing API:</p>
<ol>
<li>In Android Studio, open your project in
<a href="{@docRoot}sdk/installing/create-project.html#ProjectView">Android view</a>.
@@ -472,25 +484,24 @@
respectively. </li>
<li>Expand the <strong>Android Lint</strong> category and change the Lint settings as needed:</li>
<ul>
-<li><strong>Missing Support for Google App Indexing</strong> - Reports a warning if the app hasn’t
- implemented deep links, which are used by Google Search. This warning setting is enabled by
+<li><strong>Missing support for Google App Indexing</strong> - Reports a warning if the app hasn’t
+ implemented URLs, which are used by Google Search. This warning setting is enabled by
default.</li>
-<li><strong>Missing Support for Google App Indexing API</strong> - Reports if an app hasn’t
+<li><strong>Missing support for Google App Indexing API</strong> - Reports if an app hasn’t
implemented the App Indexing API at all. This warning setting is disabled by default.</li>
-<li><strong>Incorrect Usage of App Link for Google App Indexing</strong> - Reports deep link
+<li><strong>URL not supported by app for Google App Indexing</strong> - Reports URL
errors in manifest code. This error setting is enabled by default.</li>
</ul>
<p>For example, the following Lint warning appears for the first setting:</p>
-<p><img src="{@docRoot}images/tools/ai-lint.png" /></p>
+<p><img src="{@docRoot}images/tools/ai-lint.png" alt="Lint warning" /></p>
<li>Click <strong>OK</strong>.</li>
</ol>
-<p>To produce a list of Lint checks displayed in the <em>Inspection Results</em> window,
- follow these steps:</p>
+<p>To produce a list of Lint checks displayed in the <em>Inspection Results</em> window:</p>
<ol>
<li>In Android Studio, open your project in
<a href="{@docRoot}sdk/installing/create-project.html#ProjectView">Android view</a>
@@ -504,7 +515,7 @@
dialog, optionally click <strong>Manage</strong> to define a new profile, specify the Lint
settings you want, and then click <strong>OK</strong>.</li>
<p>In the <em>Inspections</em> dialog, you can search for the string "app indexing"
-to find the deep link and App Indexing API Lint checks. Note that changing Lint settings for a
+to find the URL and App Indexing API Lint checks. Note that changing Lint settings for a
profile in the <em>Inspections</em> dialog doesn’t change the default settings, as described in
the previous procedure. It does change the settings for profiles displayed in the
<em>Inspections</em> dialog, however.</p>
@@ -512,3 +523,87 @@
<p>The results appear in the <em>Inspection Results</em> window.</p>
</ol>
+
+
+<h2 id="appindexingtest">Performing a Google App Indexing Test</h2>
+
+<p>You can use a Google App Indexing Test to check whether Google can index
+a URL by either crawling your app page or using the App Indexing API.
+Google can index the URL if your app supports at least one of the following:
+</p>
+<ul>
+<li>Googlebot can open and crawl the page identified by the URL.</li>
+<li>Your app sends the correct data by using the App Indexing API.</li>
+</ul>
+
+<p>To perform a Google App Indexing Test: </p>
+<ol>
+<li>Add <a href="#intent">URL</a> and
+<a href="#indexing">App Indexing API</a> support to your app.
+</li>
+<li>While your project is open in Android Studio, select <strong>Tools</strong>
+> <strong>Android</strong> > <strong>Google App Indexing Test</strong>.
+</li>
+<li>In the <em>Google App Indexing Test</em> dialog, select a
+<strong>Module</strong>, <strong>URL</strong>, and <strong>Language</strong>.
+</li>
+<li>Log in if you see a message asking you to log into a Google Cloud Platform
+account.</li>
+<li>In the <em>Google App Indexing Test</em> dialog, click <strong>OK</strong>.
+</li>
+
+<p>Android Studio builds the APK and starts the test. The test can take a few
+minutes to complete. The results appear in a new tab in the Code Editor.</p>
+<p><img src="{@docRoot}images/tools/ai-appindexingtest.png"
+alt="Google App Indexing Test results" /></p>
+
+<p>If the app preview on the right shows the screen that corresponds to the URL
+you're testing, then Googlebot can find the URL.</p>
+
+<li>Correct any issues the test identifies, and repeat the test as often as
+needed.</li>
+</li>
+</ol>
+
+<p>The following table lists common errors and warnings you might encounter.</p>
+
+<table>
+ <tr>
+ <th scope="col">Warning or Error</th>
+ <th scope="col">Description</th>
+ </tr>
+
+ <tr>
+ <td>Error: Google cannot index this page.</td>
+ <td>Your app can't be crawled by Googlebot or using the App Indexing API,
+ so Google isn't able to index this app.</td>
+ </tr>
+ <tr>
+ <td>Warning: The App URL you sent by using the App Indexing API doesn't
+ match the URL opened.</td>
+ <td>When calling the App Indexing API, the URL specified in the app must
+ match the opened URL.</td>
+ </tr>
+ <tr>
+ <td>Warning: Google cannot index this page using the App Indexing API
+ because the title is empty.</td>
+ <td>When calling the App Indexing API, the title shouldn't be empty.</td>
+ </tr>
+ <tr>
+ <td>Warning: Google can index this page using Googlebot crawling but
+ identified blocked resources.</td>
+ <td>The app references other resources, and some of them are blocked or
+ temporarily unavailable. If these resources aren't critical, it might not
+ matter. Check the preview on the right to see whether the content
+ displays correctly. To fix this issue, make sure the resources aren't
+ blocked by <a href="https://support.google.com/webmasters/answer/6062608"
+ class="external-link"><code>robots.txt</code></a>.</td>
+ </tr>
+ <tr>
+ <td>Warning: Google cannot index this page using the App Indexing API.</td>
+ <td>Your app isn’t using the App Indexing API. We recommended adding App
+ Indexing API support to your app.</td>
+ </tr>
+
+</table>
+
diff --git a/docs/html/tools/help/emulator.jd b/docs/html/tools/help/emulator.jd
index 366b3bd..7b3b04f 100644
--- a/docs/html/tools/help/emulator.jd
+++ b/docs/html/tools/help/emulator.jd
@@ -1,6 +1,4 @@
-page.title=Android Emulator
-parent.title=Tools
-parent.link=index.html
+page.title=Using Android Emulator Command-Line Features
@jd:body
<div id="qv-wrapper">
@@ -8,14 +6,63 @@
<h2>In this document</h2>
<ol>
- <li><a href="#KeyMapping">Keyboard Commands</a></li>
- <li><a href="#startup-options">Command Line Parameters</a></li>
+ <li><a href="#starting">Starting and Stopping the Emulator</a></li>
+ <li><a href="#apps">Installing Applications on the Emulator</a></li>
+ <li><a href="#startup-options">Using Command Line Parameters</a></li>
+ <li><a href="#acceleration">Using Hardware Acceleration</a>
+ <ol>
+ <li><a href="#accel-graphics">Configuring Graphics Acceleration</a></li>
+ <li><a href="#accel-vm">Configuring Virtual Machine Acceleration</a></li>
+ </ol>
+ </li>
+ <li><a href="#sdcard">Using SD Card Emulation</a>
+ <ol>
+ <li><a href="#sdcard-creating">Creating an SD card image</a></li>
+ <li><a href="#sdcard-files">Copying files to an SD card image</a></li>
+ <li><a href="#sdcard-loading">Loading an SD card image</a></li>
+ </ol>
+ </li>
+ <li><a href="#diskimages">Working With Emulator Disk Images</a>
+ <ol>
+ <li><a href="#defaultimages">Default image files</a></li>
+ <li><a href="#runtimeimages">Runtime images: user data and SD card</a></li>
+ <li><a href="#temporaryimages">Temporary images</a></li>
+ </ol>
+ </li>
+ <li><a href="#emulatornetworking">Setting Up Emulator Networking</a>
+ <ol>
+ <li><a href="#networkaddresses">Network Address Space</a></li>
+ <li><a href="#networkinglimitations">Local Networking Limitations</a></li>
+ <li><a href="#redirection">Using Network Redirection</a></li>
+ <li><a href="#dns">Configuring the Emulator's DNS Settings</a></li>
+ <li><a href="#proxy">Using the Emulator with a Proxy</a></li>
+ <li><a href="#connecting">Interconnecting Emulator Instances</a></li>
+ <li><a href="#calling">Sending a Voice Call or SMS to Another Emulator Instance</a></li>
+ </ol>
+ </li>
+ <li><a href="#console">Using the Emulator Console</a>
+ <ol>
+ <li><a href="#portredirection">Port Redirection</a></li>
+ <li><a href="#geo">Geo Location Provider Emulation</a></li>
+ <li><a href="#events">Hardware Events Emulation</a></li>
+ <li><a href="#power">Device Power Characteristics</a></li>
+ <li><a href="#netstatus">Network Status</a></li>
+ <li><a href="#netdelay">Network Delay Emulation</a></li>
+ <li><a href="#netspeed">Network Speed Emulation</a></li>
+ <li><a href="#telephony">Telephony Emulation</a></li>
+ <li><a href="#sms">SMS Emulation</a></li>
+ <li><a href="#vm">VM State</a></li>
+ <li><a href="#window">Emulator Window</a></li>
+ <li><a href="#terminating">Terminating an Emulator Instance</a></li>
+ </ol>
+ </li>
+ <li><a href="#troubleshooting">Troubleshooting Emulator Problems</a></li>
</ol>
<h2>See also</h2>
<ol>
- <li><a href="{@docRoot}tools/devices/emulator.html">Using the Android Emulator</a></li>
- <li><a href="{@docRoot}tools/devices/index.html">Managing Virtual Devices</a></li>
+ <li><a href="{@docRoot}tools/devices/emulator.html">Running Apps in the Android Emulator</a></li>
+ <li><a href="{@docRoot}tools/devices/managing-avds.html">Managing AVDs with the AVD Manager</a></li>
</ol>
</div>
@@ -26,111 +73,81 @@
that runs on your computer. The emulator lets you develop and test
Android applications without using a physical device.</p>
-<p>This document is a reference to the available command line options and the keyboard mapping to
-device keys.
-For a complete guide to using the Android Emulator, see
+<p>This page describes command line features that you can use with the
+Android Emulator.
+For information about using the Android Emulator UI, see
<a href="{@docRoot}tools/devices/emulator.html">Using the Android Emulator</a>.
+</p>
-<h2 id="KeyMapping">Keyboard Commands</h2>
+<h2 id="starting">Starting and Stopping the Emulator</h2>
-<p>Table 1 summarizes the mappings between the emulator keys and the keys of your keyboard.</p>
+<p>During development and testing of your application, you install and run your
+application in the Android Emulator. You can launch the emulator as a standalone
+application from a command line, or you can run it from within your Android Studio
+development environment. In either case, you specify the AVD configuration to
+load and any startup options you want to use, as described in this document.
+</p>
-<p class="table-caption"><strong>Table 1.</strong> Emulator keyboard mapping</p>
-<table border="0" style="clear:left;">
- <tr>
- <th>Emulated Device Key </th>
- <th>Keyboard Key </th>
- </tr>
- <tr>
- <td>Home</td>
- <td>HOME</td>
- </tr>
- <tr>
- <td>Menu (left softkey)</td>
- <td>F2 <em>or</em> Page-up button</td>
- </tr>
- <tr>
- <td>Star (right softkey)</td>
- <td>Shift-F2 <em>or </em>Page Down</td>
- </tr>
- <tr>
- <td>Back</td>
- <td>ESC</td>
- </tr>
- <tr>
- <td>Call/dial button </td>
- <td>F3</td>
- </tr>
- <tr>
- <td>Hangup/end call button</td>
- <td>F4</td>
- </tr>
- <tr>
- <td>Search</td>
- <td>F5 </td>
- </tr>
- <tr>
- <td>Power button</td>
- <td>F7 </td>
- </tr>
- <tr>
- <td>Audio volume up button</td>
- <td>KEYPAD_PLUS, Ctrl-F5</td>
- </tr>
+<p>You can run your application on a single instance of the emulator or,
+depending on your needs, you can start multiple emulator instances and run your
+application in more than one emulated device. You can use the emulator's
+built-in commands to simulate GSM phone calling or SMS between emulator
+instances, and you can set up network redirection that allows emulators to send
+data to one another. For more information, see <a href="#telephony">Telephony
+Emulation</a>, <a href="#sms">SMS Emulation</a>, and
+<a href="#emulatornetworking">Emulator Networking</a></p>
- <tr>
- <td>Audio volume down button</td>
- <td>KEYPAD_MINUS, Ctrl-F6</td>
- </tr>
- <tr>
- <td>Camera button</td>
- <td>Ctrl-KEYPAD_5, Ctrl-F3</td>
- </tr>
- <tr>
- <td>Switch to previous layout orientation (for example, portrait, landscape)</td>
- <td>KEYPAD_7, Ctrl-F11</td>
- </tr>
- <tr>
- <td>Switch to next layout orientation (for example, portrait, landscape)</td>
- <td>KEYPAD_9, Ctrl-F12</td>
- </tr>
- <tr>
- <td>Toggle cell networking on/off</td>
- <td>F8</td>
- </tr>
- <tr>
- <td>Toggle code profiling</td>
- <td>F9 (only with <code>-trace</code> startup option)</td>
- </tr>
- <tr>
- <td>Toggle fullscreen mode</td>
- <td>Alt-Enter</td>
- </tr>
- <tr>
- <td>Toggle trackball mode</td>
- <td>F6</td>
- </tr>
- <tr>
- <td>Enter trackball mode temporarily (while key is pressed)</td>
- <td>Delete</td>
- </tr>
- <tr>
- <td>DPad left/up/right/down</td>
- <td>KEYPAD_4/8/6/2</td>
- </tr>
- <tr>
- <td>DPad center click</td>
- <td>KEYPAD_5</td>
- </tr>
- <tr>
- <td>Onion alpha increase/decrease</td>
- <td>KEYPAD_MULTIPLY(*) / KEYPAD_DIVIDE(/)</td>
- </tr>
-</table>
+<p>To start an instance of the emulator from the command line, navigate to the
+<code>tools/</code> folder of the SDK. Enter <code>emulator</code> command
+like this: </p>
+
+<pre>emulator -avd <avd_name> [<options>]</pre>
+
+<p>This initializes the emulator, loads an AVD configuration and displays the emulator
+window. For more information about command line options for the emulator, see the
+<a href="{@docRoot}tools/help/emulator.html">Android Emulator</a> tool reference.</p>
+
+<p class="note"><strong>Note:</strong> You can run multiple
+instances of the emulator concurrently, each with its own AVD configuration and
+storage area for user data, SD card, and so on.</p>
+
+<p>When you run your app from Android Studio, it installs and launches the
+app on your connected device or emulator (launching the emulator, if necessary).
+You can specify emulator startup options in the Run/Debug
+dialog, in the Target tab. When the emulator is running, you can issue
+console commands as described later in this document.</p>
+
+<p>If you are not working in Android Studio, see <a href="#apps">Installing Applications
+on the Emulator</a> for information about how to install your application.</p>
+
+<p>To stop an emulator instance, just close the emulator's window.</p>
+
+<p>For a reference of the emulator's startup commands and keyboard mapping, see
+the <a href="{@docRoot}tools/help/emulator.html">Android Emulator</a> tool
+reference.</p>
-<h2 id="startup-options">Command Line Parameters</h2>
+<h2 id="apps">Installing Applications on the Emulator</h2>
+
+<p>If you don't have access to Android Studio, you can install your application on the
+emulator using the <a href="{@docRoot}tools/help/adb.html#move">adb</a> utility. Before
+installing the application, you need to build and package it into an <code>.apk</code> as described
+in <a href="{@docRoot}tools/building/index.html">Building and
+Running Apps</a>. Once the application is installed, you can start the emulator from the command
+line as described previously, using any startup options necessary.
+When the emulator is running, you can also connect to the emulator instance's
+<a href="#console">console</a> to issue commands as needed.</p>
+
+<p>As you update your code, you periodically package and install it on the emulator.
+The emulator preserves the application and its state data across restarts,
+in a user-data disk partition. To ensure that the application runs properly
+as you update it, you may need to delete the emulator's user-data partition.
+To do so, start the emulator with the <code>-wipe-data</code> option.
+For more information about the user-data partition and other emulator storage,
+see <a href="#diskimages">Working with Emulator Disk Images</a>.</p>
+
+<h2 id="startup-options">Using Command Line Parameters</h2>
<p>The emulator supports a variety of options that you can specify
when launching the emulator, to control its appearance or behavior.
@@ -579,3 +596,1339 @@
<td> </td>
</tr>
</table>
+
+
+<h2 id="acceleration">Using Hardware Acceleration</h2>
+
+<p>To make the Android emulator run faster and be more responsive, you can configure it to
+take advantage of hardware acceleration, using a combination of configuration options, specific
+Android system images and hardware drivers.</p>
+
+
+<h3 id="accel-graphics">Configuring Graphics Acceleration</h3>
+
+<p class="caution"><strong>Caution:</strong> As of SDK Tools Revision 17, the graphics
+acceleration feature for the emulator is experimental; be alert for incompatibilities and
+errors when using this feature. </p>
+
+<p>Graphics acceleration for the emulator takes advantage of your development computer's graphics
+hardware, specifically its graphics processing unit (GPU), to make screen drawing faster. To use
+the graphics acceleration feature, you must have the following versions of the Android development
+tools installed:</p>
+
+<ul>
+ <li>Android SDK Tools, Revision 17 or higher</li>
+ <li>Android SDK Platform API 15, Revision 3 or higher</li>
+</ul>
+
+<p>Use the <a href="{@docRoot}sdk/installing/index.html#AddingComponents">Android SDK
+Manager</a> to install these components:</p>
+
+<p class="note"><strong>Note:</strong> Not all applications are compatible with graphics hardware
+acceleration. In particular, the Browser application and applications using the {@link
+android.webkit.WebView} component are not compatible with graphics acceleration.</p>
+
+<p>To configure an AVD to use graphics acceleration:</p>
+
+<ol>
+ <li>Make sure you have the required SDK components installed (listed above).</li>
+ <li>Start the AVD Manager and create a new AVD with the <strong>Target</strong> value of
+<strong>Android 4.0.3 (API Level 15)</strong>, revision 3 or higher.</li>
+ <li>If you want to have graphics acceleration enabled by default for this AVD, in the
+<strong>Hardware</strong> section, click <strong>New</strong>, select <strong>GPU emulation</strong>
+and set the value to <strong>Yes</strong>.
+ <p class="note"><strong>Note:</strong> You can also enable graphics acceleration when you
+start an emulator using command line options as describe in the next section.</p>
+ </li>
+ <li>Name the AVD instance and select any other configuration options.
+ <p class="caution"><strong>Caution:</strong> Do not select the <strong>Snapshot: Enabled</strong>
+option. Snapshots are not supported for emulators with graphics acceleration enabled.</p>
+ </li>
+ <li>Click <strong>Create AVD</strong> to save the emulator configuration.</li>
+</ol>
+
+<p>If you set <strong>GPU emulation</strong> to <strong>Yes</strong> for your AVD, then graphics
+acceleration is automatically enabled when you run it. If you did not enable <strong>GPU
+emulation</strong> when you created the AVD, you can still enable it at runtime.</p>
+
+<p>To enable graphics acceleration at runtime for an AVD:</p>
+
+<ul>
+ <li>If you are running the emulator from the command line, just include the {@code -gpu on}
+option:
+<pre>emulator -avd <avd_name> -gpu on</pre>
+ <p class="note"><strong>Note:</strong> You must specify an AVD configuration that uses
+Android 4.0.3 (API Level 15, revision 3) or higher system image target. Graphics acceleration is not
+available for earlier system images.</p>
+ </li>
+ <li>If you are running the emulator from Android Studio, run your Android application using an AVD
+with the {@code -gpu on} option enabled:
+ <ol>
+ <li>In Android Studio, click your Android application module folder and then select
+ <strong>Run > Edit Configurations...</strong></li>
+ <li>In the left panel of the <strong>Run/Debug Configurations</strong> dialog, select your Android
+ run configuration or create a new configuration.</li>
+ <li>Under the <strong>Target Device </strong> options,
+ select the AVD you created in the previous procedure.</li>
+ <li>In the <strong>Emulator</strong> tab, in the
+ <strong>Additional command line options</strong> field, enter:<br>
+ {@code -gpu on}</li>
+ <li>Run your Android project using this run configuration.</li>
+ </ol>
+ </li>
+</ul>
+
+
+<h3 id="accel-vm">Configuring Virtual Machine Acceleration</h2>
+
+<p class="caution"><strong>Caution:</strong> As of SDK Tools Revision 17, the virtual machine
+acceleration feature for the emulator is experimental; be alert for incompatibilities and errors
+when using this feature.</p>
+
+<p>Many modern CPUs provide extensions for running virtual machines (VMs) more efficiently. Taking
+advantage of these extensions with the Android emulator requires some additional configuration of
+your development system, but can significantly improve the execution speed. Before attempting to use
+this type of acceleration, you should first determine if your development system’s CPU supports one
+of the following virtualization extensions technologies:</p>
+
+<ul>
+ <li>Intel Virtualization Technology (VT, VT-x, vmx) extensions</li>
+ <li>AMD Virtualization (AMD-V, SVM) extensions (only supported for Linux)</li>
+</ul>
+
+<p>The specifications from the manufacturer of your CPU should indicate if it supports
+virtualization extensions. If your CPU does not support one of these virtualization technologies,
+then you cannot use virtual machine acceleration.</p>
+
+<p class="note"><strong>Note:</strong> Virtualization extensions are typically enabled through
+your computer's BIOS and are frequently turned off by default. Check the documentation for your
+system's motherboard to find out how to enable virtualization extensions.</p>
+
+<p>Once you have determined that your CPU supports virtualization extensions, make sure you can work
+within these additional requirements of running an emulator inside an accelerated virtual
+machine:</p>
+
+<ul>
+ <li><strong>x86 AVD Only</strong> - You must use an AVD that is uses an x86 system image target.
+AVDs that use ARM-based system images cannot be accelerated using the emulator configurations
+described here.</li>
+ <li><strong>Not Inside a VM</strong> - You cannot run a VM-accelerated emulator inside another
+virtual machine, such as a VirtualBox or VMWare-hosted virtual machine. You must run the emulator
+directly on your system hardware.</li>
+ <li><strong>Other VM Drivers</strong> - If you are running another virtualization technology on
+your system such as VirtualBox or VMWare, you may need to unload the driver for that virtual machine
+hosting software before running an accelerated emulator.</li>
+ <li><strong>OpenGL® Graphics</strong> - Emulation of OpenGL ES graphics may not perform at the
+same level as an actual device.</li>
+</ul>
+
+<p>To use virtual machine acceleration with the emulator, you need the following version of Android
+development tools. Use the <a href="{@docRoot}sdk/installing/index.html#AddingComponents">Android SDK
+Manager</a> to install these components:</p>
+
+<ul>
+ <li>Android SDK Tools, Revision 17 or higher</li>
+ <li>Android x86-based system image</li>
+</ul>
+
+<p>If your development environment meets all of the requirements for running a VM-accelerated
+emulator, you can use the AVD Manager to create an x86-based AVD configuration:</p>
+
+<ol>
+ <li>In the Android SDK Manager, make sure you have an x86-based <strong>System Image</strong>
+ installed for your target Android version. If you do not have an x86 <strong>System
+ Image</strong> installed, select one in the Android SDK Manager and install it.
+ <p class="note"><strong>Tip:</strong> System images are listed under each API Level in the SDK
+ Manager. An x86 system image may not be available for all API levels.</p>
+ </li>
+ <li>Start the AVD Manager and create a new AVD with an x86 value for the
+<strong>CPU/ABI</strong> field. You may need to select a specific <strong>Target</strong> value, or
+select a <strong>Target</strong> value and then select a specific <strong>CPU/ABI</strong>
+option.</li>
+ <li>Name the emulator instance and select any other configuration options.</li>
+ <li>Click <strong>Create AVD</strong> to save the emulator configuration.</li>
+</ol>
+
+<h4 id="vm-windows">Configuring VM Acceleration on Windows</h4>
+
+<p>Virtual machine acceleration for Windows requires the installation of the Intel Hardware
+Accelerated Execution Manager (Intel HAXM). The software requires an Intel CPU with
+Virtualization Technology (VT) support and one of the following operating systems:</p>
+
+<ul>
+ <li>Windows 7 (32/64-bit)</li>
+ <li>Windows Vista (32/64-bit)</li>
+ <li>Windows XP (32-bit only)</li>
+</ul>
+
+<p>To install the virtualization driver:</p>
+
+<ol>
+ <li>Start the Android SDK Manager, select <strong>Extras</strong> and then select <strong>Intel
+Hardware Accelerated Execution Manager</strong>.</li>
+ <li>After the download completes, execute {@code
+<sdk>/extras/intel/Hardware_Accelerated_Execution_Manager/IntelHAXM.exe}.</li>
+ <li>Follow the on-screen instructions to complete installation.</li>
+ <li>After installation completes, confirm that the virtualization driver is operating correctly by
+opening a command prompt window and running the following command:
+ <pre>sc query intelhaxm</pre>
+ <p>You should see a status message including the following information:</p>
+<pre>
+SERVICE_NAME: intelhaxm
+ ...
+ STATE : 4 RUNNING
+ ...
+</pre>
+ </li>
+</ol>
+
+<p>To run an x86-based emulator with VM acceleration:</p>
+<ul>
+ <li>If you are running the emulator from the command line, just specify an x86-based AVD:
+<pre>emulator -avd <avd_name></pre>
+ <p class="note"><strong>Note:</strong> You must provide an x86-based AVD configuration
+name, otherwise VM acceleration will not be enabled.</p>
+ </li>
+ <li>If you are running the emulator from Android Studio, run your Android application with an x86-based
+AVD:
+ <ol>
+ <li>In Android Studio, click your Android project folder and then select <strong>Run > Edit
+Configurations...</strong></li>
+ <li>In the left panel of the <strong>Run/Debug Configurations</strong> dialog, select your Android
+run configuration or create a new configuration.</li>
+ <li>Under the <strong>Target Device</strong> options, select the x86-based AVD you created
+previously.</li>
+ <li>Run your Android project using this run configuration.</li>
+ </ol>
+ </li>
+</ul>
+
+<p>You can adjust the amount of memory available to the Intel HAXM kernel extension by re-running
+its installer.</p>
+
+<p>You can stop using the virtualization driver by uninstalling it. Re-run the installer or use
+the Control Panel to remove the software.</p>
+
+
+<h4 id="vm-mac">Configuring VM Acceleration on Mac</h4>
+
+<p>Virtual machine acceleration on a Mac requires the installation of the Intel Hardware Accelerated
+Execution Manager (Intel HAXM) kernel extension to allow the Android emulator to make use of CPU
+virtualization extensions. The kernel extension is compatible with Mac OS X Snow Leopard (version
+10.6.0) and higher.</p>
+
+<p>To install the Intel HAXM kernel extension:</p>
+
+<ol>
+ <li>Start the Android SDK Manager, select <strong>Extras</strong> and then select <strong>Intel
+Hardware Accelerated Execution Manager</strong>.
+ <li>After the download completes, execute
+ {@code <sdk>/extras/intel/Hardware_Accelerated_Execution_Manager/IntelHAXM.dmg}.</li>
+ <li>Double click the <strong>IntelHAXM.mpkg</strong> icon to begin installation.</li>
+ <li>Follow the on-screen instructions to complete installation.</li>
+ <li>After installation completes, confirm that the new kernel extension is operating correctly by
+opening a terminal window and running the following command:
+ <pre>kextstat | grep intel</pre>
+ <p>You should see a status message containing the following extension name, indicating that the
+ kernel extension is loaded:</p>
+ <pre>com.intel.kext.intelhaxm</pre>
+ </li>
+</ol>
+
+<p>To run an x86-based emulator with VM acceleration:</p>
+<ul>
+ <li>If you are running the emulator from the command line, just specify an x86-based AVD:
+<pre>emulator -avd <avd_name></pre>
+ <p class="note"><strong>Note:</strong> You must provide an x86-based AVD configuration
+name, otherwise VM acceleration will not be enabled.</p>
+ </li>
+ <li>If you are running the emulator from Andriod Studio, run your Android application with an x86-based
+AVD:
+ <ol>
+ <li>In Android Studio, click your Android module folder and then select <strong>Run > Edit
+Configurations...</strong></li>
+ <li>In the left panel of the <strong>Run/Debug Configurations</strong> dialog, select your Android
+run configuration or create a new configuration.</li>
+ <li>Under the <strong>Target Device</strong> options,
+ select the x86-based AVD you created previously.</li>
+ <li>Run your Android project using this run configuration.</li>
+ </ol>
+ </li>
+</ul>
+
+<p>You can adjust the amount of memory available to the Intel HAXM kernel extension by re-running
+the installer.</p>
+
+<p>You can stop using the virtualization kernel driver by uninstalling it. Before removing it, shut
+down any running x86 emulators. To unload the virtualization kernel driver, run the following
+command in a terminal window:</p>
+
+<pre>sudo /System/Library/Extensions/intelhaxm.kext/Contents/Resources/uninstall.sh</pre>
+
+<h4 id="vm-linux">Configuring VM Acceleration on Linux</h4>
+
+<p>Linux-based systems support virtual machine acceleration through the KVM software package. Follow
+<a href="https://www.google.com/?q=kvm+installation">instructions for installing KVM</a> on your
+Linux system, and verify that KVM is enabled. In addition to following the installation
+instructions, be aware of these configuration requirements:</p>
+
+<ul>
+ <li>Running KVM requires specific user permissions, make sure you have sufficient permissions
+according to the KVM installation instructions.</li>
+ <li>If you use another virtualization technology in your Linux platform, unload its kernel driver
+before running the x86 emulator. For example, the VirtualBox driver program is {@code vboxdrv}.</li>
+</ul>
+
+<p>To run an x86-based emulator with VM acceleration:</p>
+
+<ul>
+ <li>If you are running the emulator from the command line, start the emulator with an x86-based
+AVD and include the KVM options:
+<pre>emulator -avd <avd_name> -qemu -m 512 -enable-kvm</pre>
+ <p class="note"><strong>Note:</strong> You must provide an x86-based AVD configuration
+name, otherwise VM acceleration will not be enabled.</p>
+ </li>
+ <li>If you are running the emulator from Android Studio, run your Android application with an
+ x86-based AVD and include the KVM options:
+ <ol>
+ <li>In Android Studio, click your Android module folder and then select <strong>Run > Edit
+Configurations...</strong></li>
+ <li>In the left panel of the <strong>Run/Debug Configurations</strong> dialog, select your Android
+run configuration or create a new configuration.</li>
+ <li>Under the <strong>Target Device</strong> options, select the x86-based AVD you created
+previously.</li>
+ <li>In the <strong>Emulator</strong> tab, in the
+ <strong>Additional command line options</strong> field, enter:
+ <pre>-qemu -m 512 -enable-kvm</pre>
+ </li>
+ <li>Run your Android project using this run configuration.</li>
+ </ol>
+ </li>
+</ul>
+
+<p class="note"><strong>Important:</strong> When using the {@code -qemu} command line option, make sure
+it is the last parameter in your command. All subsequent options are interpreted as qemu-specific
+parameters.</p>
+
+
+<h2 id="sdcard">Using SD Card Emulation</h2>
+
+<p>You can create a disk image and then load it to the emulator at startup, to
+simulate the presence of a user's SD card in the device. To do this, you can specify
+an SD card image when you create an AVD, or you can use the mksdcard utility included
+in the SDK.</p>
+
+<p>The following sections describe how to create an SD card disk image, how to copy
+files to it, and how to load it in the emulator at startup. </p>
+
+<p>Note that you can only load a disk image at emulator startup. Similarly, you
+can not remove a simulated SD card from a running emulator. However, you can
+browse, send files to, and copy/remove files from a simulated SD card either
+with adb or the emulator. </p>
+
+<p>The emulator supports emulated SDHC cards, so you can create an SD card image
+of any size up to 128 gigabytes.</p>
+
+
+<h3 id="sdcard-creating">Creating an SD card image</h3>
+
+<p>There are several ways of creating an SD card image. The easiest way is to use the
+<strong>AVD Manager</strong> to create a new SD card by specifying a size when you create an AVD.
+You can also use the {@code android} command line tool when creating an AVD. Just add the
+<code>-c</code> option to your command: </p>
+
+<pre>android create avd -n <avd_name> -t <targetID> -c <size>[K|M]</pre>
+
+<p>The <code>-c</code> option can also be used to to specify a path to an SD card
+image for the new AVD. For more information, see <a
+href="{@docRoot}tools/devices/managing-avds-cmdline.html">Managing Virtual Devices
+from the Command Line</a>.
+</p>
+
+<p>You can also use the mksdcard tool, included in the SDK, to create a FAT32 disk
+image that you can load in the emulator at startup. You can access mksdcard in
+the tools/ directory of the SDK and create a disk image like this: </p>
+
+<pre>mksdcard <size> <file></pre>
+
+<p>For example:</p>
+
+<pre>mksdcard 1024M sdcard1.iso</pre>
+
+<p>For more information, see <a
+href="{@docRoot}tools/help/mksdcard.html"><code>mksdcard</code></a>.</p>
+
+
+<h3 id="sdcard-files">Copying files to an SD card image</h3>
+
+<p>Once you have created the disk image, you can copy files to it prior to
+loading it in the emulator. To copy files, you can mount the image as a loop
+device and then copy the files to it, or you can use a utility such as {@code mtools} to
+copy the files directly to the image. The {@code mtools} package is available for Linux,
+Mac, and Windows.</p>
+
+<p>Alternatively, you can use the {@code adb push} command to move files onto an SD card image
+while it is loaded in an emulator. For more information see the <a
+href="{@docRoot}tools/help/adb.html#copyfiles">{@code adb push}</a> documentation.</p>
+
+<h3 id="sdcard-loading">Loading an SD card image</h3>
+
+<p>By default, the emulator loads the SD card image that is stored with the active
+AVD (see the <code>-avd</code> startup option).</p>
+
+<p>Alternatively, you can start the emulator with the
+<code>-sdcard</code> flag and specify the name and path of your image (relative
+to the current working directory): </p>
+
+<pre>emulator -sdcard <filepath></pre>
+
+
+<h2 id="diskimages">Working With Emulator Disk Images</h2>
+
+<p>The emulator uses mountable disk images stored on your development machine to
+simulate flash (or similar) partitions on an actual device. For example, it uses a
+disk image containing an emulator-specific kernel, the Android system, a
+ramdisk image, and writeable images for user data and simulated SD card.</p>
+
+<p>To run properly, the emulator requires access to a specific set of disk image
+files. By default, the Emulator always looks for the disk images in the
+private storage area of the AVD in use. If no images exist there when
+the Emulator is launched, it creates the images in the AVD directory based on
+default versions stored in the SDK. </p>
+
+<p class="note"><strong>Note:</strong> The default storage location for
+AVDs is in <code>~/.android/avd</code> on OS X and Linux, <code>C:\Documents and
+Settings\<user>\.android\</code> on Windows XP, and
+<code>C:\Users\<user>\.android\</code>
+on Windows Vista.</p>
+
+<p>To let you use alternate or custom versions of the image files, the emulator
+provides startup options that override the default locations and filenames of
+the image files. When you use one of these options, the emulator searches for the image
+file under the image name or location that you specify; if it can not locate the
+image, it reverts to using the default names and location.</p>
+
+<p>The emulator uses three types of image files: default image files, runtime
+image files, and temporary image files. The sections below describe how to
+override the location/name of each type of file. </p>
+
+<h3 id="defaultimages">Default image files</h3>
+
+<p>When the emulator launches, but does not find an existing user data image in
+the active AVD's storage area, it creates a new one from a default version
+included in the SDK. The default user data image is read-only. The image
+files are read-only.</p>
+
+<p>The emulator provides the <code>-system <dir></code> startup option to
+let you override the location where the emulator looks for the default
+user data image. </p>
+
+<p>The emulator also provides a startup option that lets you override the name
+of the default user data image, as described in the following table. When you use the
+option, the emulator looks in the default directory, or in a custom location
+(if you specified <code>-system <dir></code>). </p>
+
+
+<table>
+<tr>
+ <th width="10%" >Name</th>
+ <th width="30%" >Description</th>
+ <th width="40%" >Comments</th>
+</tr>
+
+<!--
+<tr>
+ <td><code>kernel-qemu.img</code></td>
+ <td>The emulator-specific Linux kernel image</td>
+ <td>Override using <code>-kernel <file></code></td>
+</tr>
+
+<tr>
+ <td><code>ramdisk.img</code></td>
+ <td>The ramdisk image used to boot the system.</td>
+ <td>Override using <code>-ramdisk <file></code></td>
+</tr>
+
+<tr>
+ <td><code>system.img</code></td>
+ <td>The <em>initial</em> Android system image.</td>
+ <td>Override using <code>-image <file></code></td>
+</tr>
+-->
+<tr>
+ <td><code>userdata.img</code></td>
+ <td>The <em>initial</em> user-data disk image</td>
+ <td>Override using <code>-initdata <file></code>. Also see
+<code>-data <file></code>, below.</td>
+</tr>
+
+</table>
+
+<h3 id="runtimeimages">Runtime images: user data and SD card</h3>
+
+<p>At runtime, the emulator reads and writes data to two disk images: a
+user-data image and (optionally) an SD card image. These images emulate the user-data
+partition and removable storage media on actual device. </p>
+
+<p>The emulator provides a default user-data disk image. At startup, the emulator
+creates the default image as a copy of the system user-data image (user-data.img),
+described above. The emulator stores the new image with the files of the active AVD.</p>
+
+<!--
+<p>The emulator provides a startup option, <code>-datadir <dir></code>,
+that you can use to override the location under which the emulator looks for the runtime
+image files. </p>
+-->
+
+<p>The emulator provides startup options to let you override the actual names and storage
+locations of the runtime images to load, as described in the following table. When you use one
+of these options, the emulator looks for the specified file(s) in the current working directory,
+in the AVD directory, or in a custom location (if you specified a path with the filename). </p>
+
+<table>
+<tr>
+ <th width="10%" >Name</th>
+ <th width="30%" >Description</th>
+ <th width="40%" >Comments</th>
+</tr>
+<tr>
+ <td><code>userdata-qemu.img</code></td>
+ <td>An image to which the emulator writes runtime user-data for a unique user.</td>
+ <td>Override using <code>-data <filepath></code>, where <code><filepath></code> is the
+path the image, relative to the current working directory. If you supply a filename only,
+the emulator looks for the file in the current working directory. If the file at <code><filepath></code> does
+not exist, the emulator creates an image from the default <code>userdata.img</code>, stores it under the name you
+specified, and persists user data to it at shutdown. </td>
+</tr>
+
+<tr>
+ <td><code>sdcard.img</code></td>
+ <td>An image representing an SD card inserted into the emulated device.</td>
+ <td>Override using <code>-sdcard <filepath></code>, where <code><filepath></code> is the
+path the image, relative to the current working directory. If you supply a filename only,
+the emulator looks for the file in the current working directory. </td>
+</tr>
+
+</table>
+
+<h4>User-Data Image</h4>
+
+<p>Each emulator instance uses a writeable user-data image to store user- and
+session-specific data. For example, it uses the image to store a unique user's
+installed application data, settings, databases, and files. </p>
+
+<p>At startup, the emulator attempts to load a user-data image stored during
+a previous session. It looks for the file in the current working directory,
+in the AVD directory described in a previous section and at the custom location/name
+that you specified at startup. </p>
+
+<ul>
+<li>If it finds a user-data image, it mounts the image and makes it available
+to the system for reading and writing of user data. </li>
+<li>If it does not find one, it creates an image by copying the system user-data
+image (userdata.img), described above. At device power-off, the system persists
+the user data to the image, so that it will be available in the next session.
+Note that the emulator stores the new disk image at the location/name that you
+specify in <code>-data</code> startup option.</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> Because of the AVD configurations used in the emulator,
+each emulator instance gets its own dedicated storage. There is no longer a need
+to use the <code>-d</code> option to specify an instance-specific storage area.</p>
+
+<h4>SD Card</h4>
+
+<P>Optionally, you can create a writeable disk image that the emulator can use
+to simulate removeable storage in an actual device. For information about how to create an
+emulated SD card and load it in the emulator, see <a href="#sdcard">SD Card Emulation</a></p>
+
+<p>You can also use the android tool to automatically create an SD Card image
+for you, when creating an AVD. For more information, see <a
+href="{@docRoot}tools/devices/managing-avds.html">Managing Virtual Devices with AVD
+Manager</a>.
+
+
+<h3 id="temporaryimages">Temporary Images</h3>
+
+<p>The emulator creates two writeable images at startup that it deletes at
+device power-off. The images are: </p>
+
+<ul>
+ <li>A writable copy of the Android system image</li>
+ <li>The <code>/cache</code> partition image</li>
+</ul>
+
+<p>The emulator does not permit renaming the temporary system image or
+persisting it at device power-off. </p>
+
+<p>The <code>/cache</code> partition image is initially empty, and is used by
+the browser to cache downloaded web pages and images. The emulator provides an
+<code>-cache <file></code>, which specifies the name of the file in which
+to persist the <code>/cache</code> image at device power-off. If <code><file>
+</code> does not exist, the emulator creates it as an empty file. </p>
+
+<p>You can also disable the use of the cache partition by specifying the
+<code>-nocache</code> option at startup. </p>
+
+
+<h2 id="emulatornetworking">Setting Up Emulator Networking</h2>
+
+<p>The emulator provides versatile networking capabilities that you can use to
+set up complex modeling and testing environments for your application. The
+sections below introduce the emulator's network architecture and capabilities.
+</p>
+
+<h3 id="networkaddresses">Network Address Space</h3>
+
+<p>Each instance of the emulator runs behind a virtual router/firewall service
+that isolates it from your development machine's network interfaces and settings
+and from the internet. An emulated device can not see your development machine
+or other emulator instances on the network. Instead, it sees only that it is
+connected through Ethernet to a router/firewall.</p>
+
+<p>The virtual router for each instance manages the 10.0.2/24 network address
+space — all addresses managed by the router are in the form of
+10.0.2.<xx>, where <xx> is a number. Addresses within this space are
+pre-allocated by the emulator/router as follows:</p>
+
+<table>
+ <tr>
+ <th>Network Address</th>
+ <th>Description</th>
+ </tr>
+ <tr>
+ <td>10.0.2.1</td>
+ <td>Router/gateway address </td>
+ </tr>
+ <tr>
+ <td>10.0.2.2</td>
+ <td>Special alias to your host loopback interface (i.e., 127.0.0.1 on your
+development machine)</td>
+ </tr>
+ <tr>
+ <td>10.0.2.3</td>
+ <td>First DNS server</td>
+ </tr>
+ <tr>
+ <td>10.0.2.4 / 10.0.2.5 / 10.0.2.6</td>
+ <td>Optional second, third and fourth DNS server (if any) </td>
+ </tr>
+ <tr>
+ <td>10.0.2.15</td>
+ <td>The emulated device's own network/ethernet interface</td>
+ </tr>
+ <tr>
+ <td>127.0.0.1</td>
+ <td>The emulated device's own loopback interface </td>
+ </tr>
+</table>
+
+<p>Note that the same address assignments are used by all running emulator
+instances. That means that if you have two instances running concurrently on
+your machine, each will have its own router and, behind that, each will have an
+IP address of 10.0.2.15. The instances are isolated by a router and can
+<em>not</em> see each other on the same network. For information about how to
+let emulator instances communicate over TCP/UDP, see <a
+href="#connecting">Connecting Emulator Instances</a>.</p>
+
+<p>Also note that the address 127.0.0.1 on your development machine corresponds
+to the emulator's own loopback interface. If you want to access services running
+on your development machine's loopback interface (a.k.a. 127.0.0.1 on your
+machine), you should use the special address 10.0.2.2 instead.</p>
+
+<p>Finally, note that each emulated device's pre-allocated addresses are
+specific to the Android emulator and will probably be very different on real
+devices (which are also very likely to be NAT-ed, i.e., behind a
+router/firewall)</p>
+
+
+<h3 id="networkinglimitations">Local Networking Limitations</h3>
+
+<p>Android applications running in an emulator can connect to the network available on your
+workstation. However, they connect through the emulator, not directly to hardware, and the emulator
+acts like a normal application on your workstation. This means that the emulator, and thus your
+Android applications, are subject to some limitations:</p>
+
+<ul>
+ <li>Communication with the emulated device may be blocked by a firewall
+program running on your machine.</li>
+ <li>Communication with the emulated device may be blocked by another
+(physical) firewall/router to which your machine is connected.</li>
+</ul>
+
+<p>The emulator's virtual router should be able to handle all outbound TCP and
+UDP connections/messages on behalf of the emulated device, provided your
+development machine's network environment allows it to do so. There are no
+built-in limitations on port numbers or ranges except the one imposed by your
+host operating system and network.</p>
+
+<p>Depending on the environment, the emulator may not be able to support other
+protocols (such as ICMP, used for "ping") might not be supported. Currently, the
+emulator does not support IGMP or multicast. </p>
+
+<h3 id="redirection">Using Network Redirection</h3>
+
+<p>To communicate with an emulator instance behind its virtual router, you need
+to set up network redirection on the virtual router. Clients can then connect
+to a specified guest port on the router, while the router directs traffic
+to/from that port to the emulated device's host port. </p>
+
+<p>To set up the network redirection, you create a mapping of host and guest
+ports/addresses on the emulator instance. There are two ways to set up
+network redirection: using emulator console commands and using the ADB tool, as
+described below. </p>
+
+
+<h4 id="consoleredir">Setting up Redirection through the Emulator Console</h4>
+
+<p>Each emulator instance provides a control console the you can connect to, to
+issue commands that are specific to that instance. You can use the
+<code>redir</code> console command to set up redirection as needed for an
+emulator instance. </p>
+
+<p>First, determine the console port number for the target emulator instance.
+For example, the console port number for the first emulator instance launched is
+5554. Next, connect to the console of the target emulator instance, specifying
+its console port number, as follows: </p>
+
+<pre><code>telnet localhost 5554</code></pre>
+
+<p>Once connected, use the <code>redir</code> command to work with redirection.
+To add a redirection, use:</p>
+
+<pre><code>add <protocol>:<host-port>:<guest-port></code>
+</pre>
+
+<p>where <code><protocol></code> is either <code>tcp</code> or <code>udp</code>,
+and <code><host-port></code> and <code><guest-port></code> sets the
+mapping between your own machine and the emulated system, respectively. </p>
+
+<p>For example, the following command sets up a redirection that handles all
+incoming TCP connections to your host (development) machine on 127.0.0.1:5000
+and will pass them through to the emulated system's 10.0.2.15:6000.:</p>
+
+<pre>redir add tcp:5000:6000</pre>
+
+<p>To delete a redirection, you can use the <code>redir del</code> command. To
+list all redirection for a specific instance, you can use <code>redir
+list</code>. For more information about these and other console commands, see
+<a href="#console">Using the Emulator Console</a>. </p>
+
+<p>Note that port numbers are restricted by your local environment. this typically
+means that you cannot use host port numbers under 1024 without special
+administrator privileges. Also, you won't be able to set up a redirection for a
+host port that is already in use by another process on your machine. In that
+case, <code>redir</code> generates an error message to that effect. </p>
+
+<h4 id="adbredir">Setting Up Redirection through ADB</h4>
+
+<p>The Android Debug Bridge (ADB) tool provides port forwarding, an alternate
+way for you to set up network redirection. For more information, see <a
+href="{@docRoot}tools/help/adb.html#forwardports">Forwarding Ports</a> in the ADB
+documentation.</p>
+
+<p>Note that ADB does not currently offer any way to remove a redirection,
+except by killing the ADB server.</p>
+
+
+<h3 id="dns">Configuring the Emulator's DNS Settings</h3>
+
+<p>At startup, the emulator reads the list of DNS servers that your system is
+currently using. It then stores the IP addresses of up to four servers on this
+list and sets up aliases to them on the emulated addresses 10.0.2.3, 10.0.2.4,
+10.0.2.5 and 10.0.2.6 as needed. </p>
+
+<p>On Linux and OS X, the emulator obtains the DNS server addresses by parsing
+the file <code>/etc/resolv.conf</code>. On Windows, the emulator obtains the
+addresses by calling the <code>GetNetworkParams()</code> API. Note that this
+usually means that the emulator ignores the content of your "hosts" file
+(<code>/etc/hosts</code> on Linux/OS X, <code>%WINDOWS%/system32/HOSTS</code>
+ on Windows).</P>
+
+<p>When starting the emulator at the command line, you can also use the
+<code>-dns-server <serverList></code> option to manually specify the
+addresses of DNS servers to use, where <serverList> is a comma-separated
+list of server names or IP addresses. You might find this option useful if you
+encounter DNS resolution problems in the emulated network (for example, an
+"Unknown Host error" message that appears when using the web browser).</p>
+
+
+<h3 id="proxy">Using the Emulator with a Proxy</h3>
+
+<p>If your emulator must access the Internet through a proxy server, you can use
+the <code>-http-proxy <proxy></code> option when starting the emulator, to
+set up the appropriate redirection. In this case, you specify proxy information
+in <code><proxy></code> in one of these formats:</p>
+
+<pre>http://<machineName>:<port></pre>
+
+<p>or</p>
+
+<pre>http://<username>:<password>@<machineName>:<port></pre>
+
+<p>The <code>-http-proxy</code> option forces the emulator to use the specified
+HTTP/HTTPS proxy for all outgoing TCP connections. Redirection for UDP is not
+currently supported.</p>
+
+<p>Alternatively, you can define the environment variable
+<code>http_proxy</code> to the value you want to use for
+<code><proxy></code>. In this case, you do not need to specify a value for
+<code><proxy></code> in the <code>-http-proxy</code> command — the
+emulator checks the value of the <code>http_proxy</code> environment variable at
+startup and uses its value automatically, if defined. </p>
+
+<p>You can use the <code>-verbose-proxy</code> option to diagnose proxy
+connection problems.</p>
+
+
+<h3 id="connecting">Interconnecting Emulator Instances</h3>
+
+<p>To allow one emulator instance to communicate with another, you must set up
+the necessary network redirection as illustrated below. </p>
+
+<p>Assume that your environment is</p>
+
+<ul>
+ <li>A is you development machine</li>
+ <li>B is your first emulator instance, running on A</li>
+ <li>C is your second emulator instance, also running on A</li>
+</ul>
+
+<p>and you want to run a server on B, to which C will connect, here is how you
+could set it up: </p>
+
+<ol>
+ <li>Set up the server on B, listening to
+<code>10.0.2.15:<serverPort></code></li>
+ <li>On B's console, set up a redirection from
+<code>A:localhost:<localPort></code> to <code>
+B:10.0.2.15:<serverPort></code></li>
+ <li>On C, have the client connect to <code>10.0.2.2:<localPort></code></li>
+</ol>
+
+<p>For example, if you wanted to run an HTTP server, you can select
+<code><serverPort></code> as 80 and <code><localPort></code> as
+8080:</p>
+
+<ul>
+ <li>B listens on 10.0.2.15:80</li>
+ <li>On B's console, issue <code>redir add tcp:8080:80</code></li>
+ <li>C connects to 10.0.2.2:8080</li>
+</ul>
+
+<h3 id="calling">Sending a Voice Call or SMS to Another Emulator Instance</h3>
+
+<p>The emulator automatically forwards simulated voice calls and SMS messages from one instance to
+another. To send a voice call or SMS, use the dialer application or SMS application, respectively,
+from one of the emulators.</p>
+
+<p>To initiate a simulated voice call to another emulator instance:</p>
+<ol>
+<li>Launch the dialer application on the originating emulator instance.</li>
+<li>As the number to dial, enter the console port number of the instance you'd like to call. You can determine
+ the console port number of the target instance by checking its window title, where the
+ console port number is reported as "Android Emulator (<port>). </li>
+<li>Press "Dial". A new inbound call appears in the target emulator instance. </li>
+</ol>
+
+<p>To send an SMS message to another emulator instance, launch the SMS application (if available). Specify the console port number of the target emulator instance as as the SMS address, enter the message text, and send the message. The message is delivered to the target emulator instance. </p>
+
+<p>You can also connect to an emulator instance's console to simulate an incoming voice call or SMS. For more information, see <a href="#telephony">Telephony Emulation</a> and <a href="#sms">SMS Emulation</a>.
+
+
+<h2 id="console">Using the Emulator Console</h2>
+
+<p>Each running emulator instance provides a console that lets you query and control the emulated
+device environment. For example, you can use the console to manage port redirection, network
+characteristics, and telephony events while your application is running on the emulator. To
+access the console and enter commands, use telnet to connect to the console's port number.</p>
+
+<p>To connect to the console of any running emulator instance at any time, use this command: </p>
+
+<pre>telnet localhost <console-port></pre>
+
+<p>An emulator instance occupies a pair of adjacent ports: a console port and an {@code adb} port.
+The port numbers differ by 1, with the {@code adb} port having the higher port number. The console
+of the first emulator instance running on a given machine uses console port 5554 and {@code adb}
+port 5555. Subsequent instances use port numbers increasing by two — for example, 5556/5557,
+5558/5559, and so on. Up to 16 concurrent emulator instances can run a console facility. </p>
+
+<p>To connect to the emulator console, you must specify a valid console port. If multiple emulator instances are running, you need to determine the console port of the emulator instance you want to connect to. You can find the instance's console port listed in the title of the instance window. For example, here's the window title for an instance whose console port is 5554:</p>
+
+<p><code>Android Emulator (5554)</code></p>
+
+<p>Alternatively, you can use the <code>adb devices</code> command, which prints a list of running emulator instances and their console port numbers. For more information, see <a href="{@docRoot}tools/help/adb.html#devicestatus">Querying for Emulator/Device Instances</a> in the adb documentation.</p>
+
+<p class="note">Note: The emulator listens for connections on ports 5554-5587 and accepts connections only from localhost.</p>
+
+<p>Once you are connected to the console, you can then enter <code>help [command]</code> to see a list of console commands and learn about specific commands. </p>
+
+<p>To exit the console session, use <code>quit</code> or <code>exit</code>.</p>
+
+<p>The following sections below describe the major functional areas of the console.</p>
+
+
+<h3 id="portredirection">Port Redirection</h3>
+
+<p>You can use the console to add and remove port redirection while the emulator is running. After
+you connect to the console, manage port redirection by entering the following command:</p>
+
+<pre>redir <list|add|del> </pre>
+
+<p>The <code>redir</code> command supports the subcommands listed in the table below. </p>
+
+<table>
+<tr>
+ <th width="25%" >Subcommand
+ <th width="30%" >Description</th>
+ <th width="35%">Comments</th>
+</tr>
+
+ <tr>
+ <td><code>list</code></td>
+ <td>List the current port redirection.</td>
+ <td> </td>
+ </tr>
+
+
+<tr>
+ <td><code>add <protocol>:<host-port>:<guest-port></code></td>
+ <td>Add a new port redirection.</td>
+<td><ul><li><protocol> must be either "tcp" or "udp"</li>
+<li><host-port> is the port number to open on the host</li>
+<li><guest-port> is the port number to route data to on the emulator/device</li>
+</ul></td>
+</tr>
+<tr>
+ <td><code>del <protocol>:<host-port></code></td>
+ <td>Delete a port redirection.</td>
+<td>The meanings of <protocol> and <host-port> are listed in the previous row.</td>
+</tr>
+</table>
+
+
+<h3 id="geo">Geo Location Provider Emulation</h3>
+
+<p>You can use the console to set the geographic location reported to the applications running
+inside an emulator. Use the <code>geo</code> command to send a simple GPS fix to the
+emulator, with or without NMEA 1083 formatting:</p>
+
+<pre>geo <fix|nmea></pre>
+
+<p>The <code>geo</code> command supports the subcommands listed in the table below.</p>
+
+<table>
+<tr>
+ <th width="25%">Subcommand</th>
+ <th width="30%">Description</th>
+ <th width="35%">Comments</th>
+</tr>
+
+ <tr>
+ <td><code>fix <longitude> <latitude> [<altitude>]</code></td>
+ <td>Send a simple GPS fix to the emulator instance.</td>
+ <td>Specify longitude and latitude in decimal degrees. Specify altitude in meters.</td>
+ </tr>
+<tr>
+ <td><code>nmea <sentence></code></td>
+ <td>Send an NMEA 0183 sentence to the emulated device, as if it were sent from an emulated GPS modem.</td>
+<td><code><sentence></code> must begin with '$GP'. Only '$GPGGA' and '$GPRCM' sentences are currently supported.</td>
+</tr>
+</table>
+
+<p>You can issue the <code>geo</code> command as soon as an emulator instance is running. The
+emulator sets the location you enter by creating a mock location provider. This provider responds to
+location listeners set by applications, and also supplies the location to the {@link
+android.location.LocationManager}. Any application can query the location manager to obtain the
+current GPS fix for the emulated device by calling:
+
+<pre>LocationManager.getLastKnownLocation("gps")</pre>
+
+<p>For more information about the Location Manager, see {@link android.location.LocationManager}.
+</p>
+
+<h3 id="events">Hardware Events Emulation</h3>
+
+<p>The {@code event} console commands sends hardware events to the emulator. The syntax for this
+command is as follows:</p>
+
+<pre>event <send|types|codes|text></pre>
+
+<p>The <code>event</code> command supports the subcommands listed in the table below. </p>
+
+<table>
+<tr>
+ <th width="25%" >Subcommand
+ <th width="30%" >Description</th>
+ <th width="35%">Comments</th>
+</tr>
+
+ <tr>
+ <td><code>send <type>:<code>:<value> [...]</code></td>
+ <td>Send one or more events to the Android kernel. </td>
+ <td>You can use text names or integers for <code><type></code> and <code><value></code>.</td>
+ </tr>
+<tr>
+ <td><code>types</code></td>
+ <td>List all <code><type></code> string aliases supported by the <code>event</code> subcommands.</td>
+<td> </td>
+</tr>
+<tr>
+ <td><code>codes <type></code></td>
+ <td>List all <code><codes></code> string aliases supported by the <code>event</code>
+ subcommands for the specified <code><type></code>.</td>
+<td> </td>
+</tr>
+<tr>
+ <td><code>event text <message></code></td>
+ <td>Simulate keypresses to send the specified string of characters as a message,</td>
+<td>The message must be a UTF-8 string. Unicode posts will be reverse-mapped according to the current device keyboard. Unsupported characters will be discarded silently.</td>
+</tr>
+</table>
+
+
+<h3 id="power">Device Power Characteristics</h3>
+
+<p>The {@code power} command controls the power state reported by the emulator to applications. The
+syntax for this command is as follows: </p>
+
+<pre>power <display|ac|status|present|health|capacity></pre>
+
+<p>The <code>event</code> command supports the subcommands listed in the table below. </p>
+
+<table>
+<tr>
+ <th width="25%" >Subcommand </th>
+ <th width="30%" >Description</th>
+ <th width="35%">Comments</th>
+</tr>
+
+ <tr>
+ <td><code>display</code></td>
+ <td>Display battery and charger state.</td>
+ <td> </td>
+ </tr>
+<tr>
+ <td><code>ac <on|off></code></td>
+ <td>Set AC charging state to on or off. </td>
+<td> </td>
+</tr>
+<tr>
+ <td><code>status <unknown|charging|discharging|not-charging|full></code></td>
+ <td>Change battery status as specified.</td>
+<td> </td>
+</tr>
+
+<tr>
+ <td><code>present <true|false></code></td>
+ <td>Set battery presence state.</td>
+<td> </td>
+</tr>
+<tr>
+ <td><code>health <unknown|good|overheat|dead|overvoltage|failure></code></td>
+ <td>Set battery health state.</td>
+<td> </td>
+</tr>
+<tr>
+ <td><code>capacity <percent></code></td>
+ <td>Set remaining battery capacity state (0-100).</td>
+<td> </td>
+</tr>
+</table>
+
+
+<h3 id="netstatus">Network Status</h3>
+
+<p>You can use the console to check the network status and current delay and speed characteristics. To do so, connect to the console and use the <code>netstatus</code> command. Here's an example of the command and its output. </p>
+
+<pre>network status
+</pre>
+
+
+<h3 id="netdelay">Network Delay Emulation</h3>
+
+<p>The emulator lets you simulate various network latency levels, so that you can test your
+application in an environment more typical of the actual conditions in which it will run. You can
+set a latency level or range at emulator startup or you can use the console to change the latency,
+while the application is running in the emulator. </p>
+
+<p>To set latency at emulator startup, use the <code>-netdelay</code> emulator option with a
+supported <code><delay></code> value, as listed in the table below. Here are some
+examples:</p>
+
+<pre>emulator -netdelay gprs
+emulator -netdelay 40 100</pre>
+
+<p>To make changes to network delay while the emulator is running, connect to the console and use
+the <code>netdelay</code> command with a supported <code><delay></code> value from the table
+below.</p>
+
+<pre>network delay gprs</pre>
+
+<p>The format of network <delay> is one of the following (numbers are milliseconds):</p>
+
+<table style="clear:right;width:100%;">
+<tr>
+ <th width="30%" >Value</th>
+ <th width="35%" >Description</th><th width="35%">Comments</th></tr>
+
+ <tr><td><code>gprs</code></td><td>GPRS</td>
+ <td>(min 150, max 550)</td>
+ </tr>
+
+<tr><td><code>edge</code></td><td>EDGE/EGPRS</td>
+<td>(min 80, max 400)</td>
+</tr>
+<tr><td><code>umts</code></td><td>UMTS/3G</td>
+<td>(min 35, max 200)</td>
+</tr>
+<tr><td><code>none</code></td><td>No latency</td><td>(min 0, max 0)</td></tr>
+<tr><td><code><num></code></td>
+<td>Emulate an exact latency (milliseconds).</td>
+<td> </td></tr>
+<tr><td><code><min>:<max></code></td>
+<td>Emulate an specified latency range (min, max milliseconds).</td>
+<td> </td></tr>
+</table>
+
+
+<h3 id="netspeed">Network Speed Emulation</h3>
+
+<p>The emulator also lets you simulate various network transfer rates.
+You can set a transfer rate or range at emulator startup or you can use the console to change the
+rate, while the application is running in the emulator.</p>
+
+<p>To set the network speed at emulator startup, use the <code>-netspeed</code> emulator option with a supported
+<code><speed></code> value, as listed in the table below. Here are some examples:</p>
+
+<pre>emulator -netspeed gsm
+emulator -netspeed 14.4 80</pre>
+
+<p>To make changes to network speed while the emulator is running, connect to the console and use
+the <code>netspeed</code> command with a supported <code><speed></code> value from the table
+below.</p>
+
+<pre>network speed 14.4 80</pre>
+
+<p>The format of network <code><speed></code> is one of the following (numbers are
+kilobits/sec):</p>
+<table style="clear:right;width:100%;">
+<tbody>
+<tr>
+ <th width="30%">Value</th>
+ <th width="35%">Description</th><th width="35%">Comments</th></tr>
+
+ <tr>
+ <td><code>gsm</code></td>
+ <td>GSM/CSD</td><td>(Up: 14.4, down: 14.4)</td></tr>
+<tr>
+ <td><code>hscsd</code></td>
+ <td>HSCSD</td><td>(Up: 14.4, down: 43.2)</td></tr>
+<tr>
+ <td><code>gprs</code></td>
+ <td>GPRS</td><td>(Up: 40.0, down: 80.0)</td></tr>
+<tr>
+ <td><code>edge</code></td>
+ <td>EDGE/EGPRS</td>
+ <td>(Up: 118.4, down: 236.8)</td>
+</tr>
+<tr>
+ <td><code>umts</code></td>
+ <td>UMTS/3G</td><td>(Up: 128.0, down: 1920.0)</td></tr>
+<tr>
+ <td><code>hsdpa</code></td>
+ <td>HSDPA</td><td>(Up: 348.0, down: 14400.0)</td></tr>
+<tr>
+ <td><code>full</code></td>
+ <td>no limit</td><td>(Up: 0.0, down: 0.0)</td></tr>
+<tr>
+ <td><code><num></code></td>
+ <td>Set an exact rate used for both upload and download.</td><td></td></tr>
+<tr>
+ <td><code><up>:<down></code></td>
+ <td>Set exact rates for upload and download separately.</td><td></td></tr>
+</table>
+
+
+<h3 id="telephony">Telephony Emulation</h3>
+
+<p>The Android emulator includes its own GSM emulated modem that lets you simulate telephony
+functions in the emulator. For example, you can simulate inbound phone calls, establish data
+connections and terminate them. The Android system handles simulated calls exactly as it would
+actual calls. The emulator does not support call audio.</p>
+
+<p>You can use the {@code gsm} command to access the emulator's telephony functions after connecting
+to the console. The syntax for this command is as follows:</p>
+
+<pre>gsm <call|accept|busy|cancel|data|hold|list|voice|status> </pre>
+
+<p>The <code>gsm</code> command supports the subcommands listed in the table below. </p>
+<table>
+ <tr>
+ <th>Subcommand </th>
+ <th width="25%">Description</th>
+ <th>Comments</th>
+ </tr>
+ <tr>
+ <td><code>call <phonenumber></code></td>
+ <td>Simulate an inbound phone call from <phonenumber>.</td>
+ <td> </td>
+ </tr>
+ <tr>
+ <td><code>accept <phonenumber></code></td>
+ <td>Accept an inbound call from <phonenumber> and change the call's state "active".</td>
+ <td>You can change a call's state to "active" only if its current state is "waiting" or "held".</td>
+ </tr>
+ <tr>
+ <td><code>busy <phonenumber></code></td>
+ <td>Close an outbound call to <phonenumber> and change the call's state to "busy".</td>
+ <td>You can change a call's state to "busy" only if its current state is "waiting".</td>
+ </tr>
+ <tr>
+ <td><code>cancel <phonenumber></code></td>
+ <td>Terminate an inbound or outbound phone call to/from <phonenumber>.</td>
+ <td> </td>
+ </tr>
+ <tr>
+ <td><code>data <state></code></td>
+ <td>Change the state of the GPRS data connection to <state>.</td>
+ <td>Supported <state> values are:<br />
+ <ul>
+ <li><code>unregistered</code> -- No network available</li>
+ <li><code>home</code> -- On local network, non-roaming</li>
+ <li><code>roaming</code> -- On roaming network</li>
+ <li><code>searching</code> -- Searching networks</li>
+ <li><code>denied</code> -- Emergency calls only</li>
+ <li><code>off</code> -- Same as 'unregistered'</li>
+ <li><code>on</code> -- same as 'home'</li>
+ </ul>
+ </td>
+ </tr>
+ <tr>
+ <td><code>hold</code></td>
+ <td>Change the state of a call to "held". </td>
+ <td>You can change a call's state to "held" only if its current state is "active" or "waiting". </td>
+ </tr>
+ <tr>
+ <td><code>list</code></td>
+ <td>List all inbound and outbound calls and their states.</td>
+ <td> </td>
+ </tr>
+ <tr>
+ <td><code>voice <state></code></td>
+ <td>Change the state of the GPRS voice connection to <state>.</td>
+ <td>Supported <state> values are:<br />
+ <ul>
+ <li><code>unregistered</code> -- No network available</li>
+ <li><code>home</code> -- On local network, non-roaming</li>
+ <li><code>roaming</code> -- On roaming network</li>
+ <li><code>searching</code> -- Searching networks</li>
+ <li><code>denied</code> -- Emergency calls only</li>
+ <li><code>off</code> -- Same as 'unregistered'</li>
+ <li><code>on</code> -- Same as 'home'</li>
+ </ul>
+ </td>
+ </tr>
+
+ <tr>
+ <td><code>status</code></td>
+ <td>Report the current GSM voice/data state.</td>
+ <td>Values are those described for the <code>voice</code> and <code>data</code> commands.</td>
+ </tr>
+</table>
+
+
+<h3 id="sms">SMS Emulation</h3>
+
+<p>The Android emulator console lets you generate an SMS message and direct it to an emulator
+instance. Once you connect to an emulator instance, you can generate an emulated incoming SMS using
+the following command:</p>
+
+<pre>sms send <senderPhoneNumber> <textmessage></pre>
+
+<p>where <code><senderPhoneNumber></code> contains an arbitrary numeric string. </p>
+
+<p>The console forwards the SMS message to the Android framework, which passes it through to an application that handles that message type. </p>
+
+
+<h3 id="vm">VM State</h3>
+
+<p>You can use the <code>vm</code> command to control the VM on an emulator instance. The syntax for
+this command is as follows: </p>
+
+<pre>vm <start|stop|status></pre>
+
+<p>The <code>vm</code> command supports the subcommands listed in the table below. </p>
+
+<table>
+<tr>
+ <th width="25%">Subcommand</th>
+ <th width="30%">Description</th>
+ <th width="35%">Comments</th>
+</tr>
+<tr>
+ <td><code>start</code></td>
+ <td>Start the VM on the instance. </td>
+ <td> </td>
+</tr>
+<tr>
+ <td><code>stop</code></td>
+ <td>Stop the VM on the instance. </td>
+ <td> </td>
+</tr>
+<tr>
+ <td><code>start</code></td>
+ <td>Display the current status of the VM (running or stopped). </td>
+ <td> </td>
+</tr>
+</table>
+
+
+<h3 id="window">Emulator Window</h3>
+
+<p>You can use the <code>window</code> command to manage the emulator window. The syntax for this
+command is as follows: </p>
+
+<pre>window <scale></pre>
+
+<p>The <code>vm</code> command supports the subcommands listed in the table below. </p>
+
+<table>
+<tr>
+ <th width="25%">Subcommand</th>
+ <th width="30%">Description</th>
+ <th width="35%">Comments</th>
+</tr>
+<tr>
+ <td><code>scale <scale></code></td>
+ <td>Scale the emulator window.</td>
+ <td>A number between 0.1 and 3 that sets the scaling factor. You can
+ also specify scale as a DPI value if you add the suffix "dpi" to the scale value. A value of "auto"
+ tells the emulator to select the best window size.</td>
+</tr>
+</table>
+
+
+<h3 id="terminating">Terminating an Emulator Instance</h3>
+
+<p>You can terminate an emulator instance through the console, using the <code>kill</code> command.</p>
+
+
+
+
+<h2 id="troubleshooting">Troubleshooting Emulator Problems</h2>
+
+<p>The {@code adb} utility sees the emulator as an actual physical device. For this reason, you
+might have to use the {@code -d} flag with some common {@code adb} commands, such as
+<code>install</code>. The {@code -d} flag lets you specify which of several connected devices to use
+as the target of a command. If you don't specify {@code -d}, the emulator targets the first
+device in its list. For more information about {@code adb}, see <a
+href="{@docRoot}tools/help/adb.html">Android Debug Bridge</a>.</p>
+
+<p>For emulators running on Mac OS X, if you see an error {@code Warning: No DNS servers found}
+when starting the emulator, check to see whether you have an <code>/etc/resolv.conf</code> file. If
+not, please run the following line in a command window:</p>
+ <pre>ln -s /private/var/run/resolv.conf /etc/resolv.conf</pre>
+
+<p>See <a href="{@docRoot}resources/faq/index.html">Frequently Asked Questions</a> for more
+troubleshooting information. </p>
diff --git a/docs/html/tools/performance/index.jd b/docs/html/tools/performance/index.jd
index fa5af86..299b05e 100644
--- a/docs/html/tools/performance/index.jd
+++ b/docs/html/tools/performance/index.jd
@@ -22,6 +22,17 @@
visualize the rendering, compute, memory, and battery performance of your
app.</p>
+<p class="note">
+ <strong>Note:</strong> While profiling an app, you should <a href=
+ "{@docRoot}tools/building/building-studio.html#disable-ir">disable Instant
+ Run</a>. There is a small performance impact when <a href=
+ "{@docRoot}tools/building/building-studio.html#instant-run">using Instant
+ Run</a> and a slightly larger impact when updating methods. This
+ performance impact could interfere with information provided by performance
+ profiling tools. Additionally, the stub methods generated while using the
+ feature can complicate stack traces.
+</p>
+
<h2 id="rendering-tools">Rendering Analysis Tools</h2>
<p>Visualize the rendering behavior and performance of your app.</p>
diff --git a/docs/html/tools/revisions/gradle-plugin.jd b/docs/html/tools/revisions/gradle-plugin.jd
index 540bbcd..6a35cab 100644
--- a/docs/html/tools/revisions/gradle-plugin.jd
+++ b/docs/html/tools/revisions/gradle-plugin.jd
@@ -3,42 +3,249 @@
@jd:body
<div id="qv-wrapper">
-<div id="qv">
+ <div id="qv">
+ <h2>
+ In this document
+ </h2>
- <h2>See also</h2>
- <ol>
- <li><a href="{@docRoot}sdk/installing/studio-build.html">Build System Overview</a></li>
- <li><a href="{@docRoot}tools/building/plugin-for-gradle.html">Android Plugin for Gradle</a></li>
- </ol>
+ <ol>
+ <li>
+ <a href="#updating-plugin">Updating the Android Plugin for Gradle
+ Version</a>
+ </li>
-</div>
+ <li>
+ <a href="#updating-gradle">Updating the Gradle Version</a>
+ </li>
+
+ <li>
+ <a href="#revisions">Revisions</a>
+ </li>
+ </ol>
+
+ <h2>
+ See also
+ </h2>
+
+ <ol>
+ <li>
+ <a href="{@docRoot}sdk/installing/studio-build.html">Build System
+ Overview</a>
+ </li>
+
+ <li>
+ <a href="{@docRoot}tools/building/plugin-for-gradle.html">Android
+ Plugin for Gradle</a>
+ </li>
+ </ol>
+ </div>
</div>
+<p>
+ The Android build system uses the Android Plugin for Gradle to support
+ building Android applications with the <a href=
+ "http://www.gradle.org/">Gradle</a> build toolkit. The plugin runs
+ independent of Android Studio so the plugin and the Gradle build system can
+ be updated independently of Android Studio.
+</p>
-<p>The Android build system uses the Android Plugin for Gradle to support building Android
-applications with the <a href="http://www.gradle.org/">Gradle</a> build toolkit. The plugin runs
-independent of Android Studio so the plugin and the Gradle build system can be updated
-independently of Android Studio.</p>
+<h2 id="updating-plugin">
+ Updating the Android Plugin for Gradle
+</h2>
-<p class="note"><strong>Note:</strong> When you update Android Studio or open a project in a
-previous version of Android Studio, Android Studio prompts you to automatically update the plugin
-and Gradle to the latest available versions. You can choose to accept these updates based
-on your project's build requirements. </p>
+<p>
+ When you update Android Studio, you may receive a prompt to automatically
+ update the Android Plugin for Gradle to the latest available version. You
+ can choose to accept the update or manually specify a version based on
+ your project's build requirements.
+</p>
+<p>
+ You can specify the <a href=
+ "{@docRoot}tools/building/plugin-for-gradle.html">Android Plugin for
+ Gradle</a> version in either the <strong>File</strong> > <strong>Project
+ Structure</strong> > <strong>Project</strong> menu in Android Studio, or
+ the top-level <code>build.gradle</code> file. The plugin version applies to
+ all modules built in that Android Studio project. The following example sets
+ the Android Plugin for Gradle to version 2.0.0 from the
+ <code>build.gradle</code> file:
+</p>
-<h2 id="revisions">Revisions</h2>
+<pre>
+buildscript {
+ ...
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.0.0'
+ }
+}
+</pre>
+<p class="caution">
+ <strong>Caution:</strong> You should not use dynamic dependencies in version
+ numbers, such as <code>'com.android.tools.build:gradle:2.+'</code>. Using
+ this feature can cause unexpected version updates and difficulty resolving
+ version differences.
+</p>
-<p>The sections below provide notes about successive releases of
-the Android Plugin for Gradle, as denoted by revision number. To determine what revision of the
-plugin you are using, check the version declaration in the project-level
-<strong>build.gradle</strong> file. </p>
+<p>
+ If the specified plugin version has not been downloaded, Gradle downloads it
+ the next time you build your project or click <strong>Tools</strong> >
+ <strong>Android</strong> > <strong>Sync Project with Gradle Files</strong>
+ from the Android Studio main menu.
+</p>
-<p>For a summary of known issues in Android Plugin for Gradle, see <a
-href="http://tools.android.com/knownissues">http://tools.android.com/knownissues</a>.</p>
+<h2 id="updating-gradle">
+ Updating Gradle
+</h2>
+
+<p>
+ When you update Android Studio, you may receive a prompt to automatically
+ update Gradle to the latest available version. You can choose to accept the
+ update or manually specify a version based on your project's build
+ requirements.
+</p>
+
+<p>
+ You can specify the Gradle version in either the <strong>File</strong> >
+ <strong>Project Structure</strong> > <strong>Project</strong> menu in
+ Android Studio, or by editing the Gradle distribution reference in the
+ <code>gradle/wrapper/gradle-wrapper.properties</code> file. The following
+ example sets the Gradle version to 2.10 in the
+ <code>gradle-wrapper.properties</code> file.
+</p>
+
+<pre>
+...
+distributionUrl = https\://services.gradle.org/distributions/gradle-2.10-all.zip
+...
+</pre>
+
+<h2 id="revisions">
+ Revisions
+</h2>
+
+<p>
+ For a summary of known issues in Android Plugin for Gradle, visit the
+ <a class="external-link" href="http://tools.android.com/knownissues">Android
+ Tools Project Site</a>.
+</p>
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/styles/disclosure_up.png" class="toggle-content-img"
+ alt=""/>Android Plugin for Gradle, Revision 2.0.0</a> <em>(March 2016)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+ <dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Gradle 2.10 or higher.
+ </li>
+
+ <li>
+ <a href="{@docRoot}tools/revisions/build-tools.html">Build Tools 21.1.1</a>
+ or higher.
+ </li>
+ </ul>
+ </dd>
+
+ <dt>New:</dt>
+ <dd>
+ <ul>
+ <li>Enables <a href=
+ "{@docRoot}tools/building/building-studio.html#instant-run">Instant Run</a> by
+ supporting bytecode injection, and pushing code and resource updates to a
+ running app on the emulator or a physical device.
+ </li>
+
+ <li>Added support for incremental builds, even when the app isn’t running.
+ Full build times are improved by pushing incremental changes through the
+ <a href="{@docRoot}tools/help/adb.html">Android Debug Bridge</a> to the
+ connected device.
+ </li>
+
+ <li>Added <code>maxProcessCount</code> to control how many slave dex processes can
+ be spawned concurrently. The following code, in the module-level
+ <code>build.gradle</code> file, sets the maximum number of concurrent processes
+ to 4:
+<pre>
+android {
+ ...
+ dexOptions {
+ maxProcessCount = 4
+ }
+}
+</pre>
+ </li>
+
+ <li>Added an experimental code shrinker to support pre-dexing and reduce re-dexing
+ of dependencies, which are not supported with Proguard. This improves the build
+ speed of your debug build variant. Because the experimental shrinker does not
+ support optimization and obfuscation, you should enable Proguard for your
+ release builds. To enable the experimental shrinker for your debug builds, add
+ the following to your module-level <code>build.gradle</code> file:
+
+<pre>
+android {
+ ...
+ buildTypes {
+ debug {
+ minifyEnabed true
+ useProguard false
+ }
+ release {
+ minifyEnabed true
+ useProguard true // this is a default setting
+ }
+ }
+}
+</pre>
+ </li>
+
+ <li>Added logging support and improved performance for the resource shrinker.
+ The resource shrinker now logs all of its operations into a <code>resources.txt</code>
+ file located in the same folder as the Proguard log files.
+ </li>
+ </ul>
+ </dd>
+
+ <dt>Changed behavior:</dt>
+ <dd>
+ <ul>
+ <li>When <code>minSdkVersion</code> is set to 18 or higher, APK signing uses
+ SHA256.
+ </li>
+
+ <li>DSA and ECDSA keys can now sign APK packages.
+
+ <p class="note">
+ <strong>Note:</strong> The <a href=
+ "{@docRoot}training/articles/keystore.html">Android keystore</a> provider no
+ longer supports <a href=
+ "{@docRoot}about/versions/marshmallow/android-6.0-changes.html#behavior-keystore">
+ DSA keys on Android 6.0</a> (API level 23) and higher.
+ </p>
+
+ </li>
+ </ul>
+ </dd>
+
+ <dt>Fixed issues:</dt>
+ <dd>
+ <ul>
+ <li>Fixed an issue that caused duplicate AAR dependencies in both
+ the test and main build configurations.
+ </li>
+ </ul>
+ </dd>
+ </div>
+</div>
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/styles/disclosure_down.png" class="toggle-content-img"
alt=""/>Android Plugin for Gradle, Revision 1.5.0</a> <em>(November 2015)</em>
</p>
@@ -546,9 +753,6 @@
</div>
</div>
-
-
-
<div class="toggle-content closed">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/styles/disclosure_down.png" class="toggle-content-img"
@@ -577,47 +781,4 @@
</ul>
</dd>
</div>
-</div>
-
-
-
-
-<h2>Updating the Android Plugin for Gradle Version</h2>
-<p>The Android Plugin for Gradle version is specified in the
-<strong>File > Project Structure > Project</strong> menu and the project-level
-<code>build.gradle</code> file. The plugin version applies to all modules built in that
-Android Studio project. This example sets the Android Plugin for Gradle to version 1.1.0 from the <code>build.gradle</code> file:
-<pre>
-...
- dependencies {
- classpath 'com.android.tools.build:gradle:1.1.0'
- }
-...
-</pre>
-
-
-<p class="caution"><strong>Caution:</strong> You should not use dynamic dependencies (+) in
-version numbers. Using this feature can cause unexpected version updates and difficulty
-resolving version differences. </p>
-
-<p>If you're building with Gradle but not using Android Studio, the build process downloads the
-latest Android Plugin for Gradle when it runs. </p>
-
-
-
-<h2>Updating the Gradle Version </h2>
-
-<p>Android Studio requires Gradle version 2.2.1 or later. To view and
-update the Gradle version, edit the Gradle distribution reference in the
-<code>gradle/wrapper/gradle-wrapper.properties</code> file. This example sets the
-Gradle version to 2.2.1.</p>
-
-<pre>
-...
-distributionUrl=http\://services.gradle.org/distributions/gradle-2.2.1-all.zip
-...
-</pre>
-
-<p>For more details about the supported Android Plugin for Gradle properties and syntax, click
-the link to the
-<a href="{@docRoot}tools/building/plugin-for-gradle.html">Plugin Language Reference</a>.</p>
\ No newline at end of file
+</div>
\ No newline at end of file
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index 3ce0d11..baa51bc 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -97,7 +97,7 @@
<li><a href="<?cs var:toroot ?>tools/debugging/annotations.html">
<span class="en">Improving Code Inspection with Annotations</span></a></li>
<li><a href="<?cs var:toroot ?>tools/help/app-link-indexing.html">
- <span class="en">Deep Link and App Indexing API Support</span></a></li>
+ <span class="en">Supporting URLs and App Indexing in Android Studio</span></a></li>
</ul>
</li>
@@ -123,6 +123,16 @@
<li class="nav-section">
<div class="nav-section-header">
+ <a href="<?cs var:toroot ?>tools/devices/emulator.html">
+ <span class="en">Android Emulator</span></a></div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>tools/help/emulator.html">Android Emulator
+ Command-Line Features</a></li>
+ </ul>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header">
<a href="<?cs var:toroot ?>tools/debugging/debugging-studio.html">
<span class="en">Debugging Tools</span></a></div>
<ul>
@@ -219,14 +229,7 @@
<li><a href="<?cs var:toroot ?>tools/help/proguard.html" zh-cn-lang="ProGuard">ProGuard</a></li>
<li><a href="<?cs var:toroot ?>tools/help/gltracer.html">Tracer for OpenGL ES</a></li>
- <li class="nav-section">
- <div class="nav-section-header">
- <a href="<?cs var:toroot ?>tools/devices/emulator.html">
- <span class="en">Virtual Device Emulator</span></a></div>
- <ul>
- <li><a href="<?cs var:toroot ?>tools/help/emulator.html">Command Reference</a></li>
- </ul>
- </li>
+
<li><a href="<?cs var:toroot ?>tools/help/zipalign.html">zipalign</a></li>
</ul>
@@ -251,7 +254,7 @@
<li><a href="<?cs var:toroot ?>tools/building/manifest-merge.html">
<span class="en">Manifest Merging</span></a></li>
<li><a href="<?cs var:toroot ?>tools/building/multidex.html">
- <span class="en">Apps Over 65K Methods</span></a></li>
+ <span class="en">Apps Over 64K Methods</span></a></li>
</ul>
</li><!-- end of build system -->
diff --git a/docs/html/training/app-indexing/index.jd b/docs/html/training/app-indexing/index.jd
index a1a47e9..60f40b4 100644
--- a/docs/html/training/app-indexing/index.jd
+++ b/docs/html/training/app-indexing/index.jd
@@ -22,7 +22,7 @@
target="_blank">App Indexing for Google Search</a></li>
<li><a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent
Filters</a></li>
-<li><a href="{@docRoot}tools/help/app-link-indexing.html">Deep Link and App Indexing API Support in Android Studio</a></li>
+<li><a href="{@docRoot}tools/help/app-link-indexing.html">Supporting URLs and App Indexing in Android Studio</a></li>
</ul>
</div>
</div>
diff --git a/docs/html/training/app-links/index.jd b/docs/html/training/app-links/index.jd
index 27b6480..80309ee1 100644
--- a/docs/html/training/app-links/index.jd
+++ b/docs/html/training/app-links/index.jd
@@ -16,7 +16,7 @@
</ol>
<h2>See also</h2>
<ol>
- <li><a href="{@docRoot}tools/help/app-link-indexing.html">Deep Link and App Indexing API Support in Android Studio</a></li>
+ <li><a href="{@docRoot}tools/help/app-link-indexing.html">Supporting URLs and App Indexing in Android Studio</a></li>
</ol>
</div>
</div>
diff --git a/docs/html/training/testing/start/index.jd b/docs/html/training/testing/start/index.jd
index a4b4aea..74617b0 100644
--- a/docs/html/training/testing/start/index.jd
+++ b/docs/html/training/testing/start/index.jd
@@ -6,69 +6,153 @@
@jd:body
<div id="tb-wrapper">
-<div id="tb">
+ <div id="tb">
-<!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
-<h2>Dependencies and prerequisites</h2>
-<ul>
- <li><a href="{@docRoot}tools/studio/index.html">Android Studio (latest version)</a>.</li>
-</ul>
+ <h2>
+ Dependencies and prerequisites
+ </h2>
-<h2>This lesson teaches you to</h2>
-<ol>
-<li><a href="#setup">Set Up Your Testing Environment</a></li>
-<li><a href="#build">Build and Run Your Tests</a></li>
-</ol>
+ <ul>
+ <li>
+ <a href="{@docRoot}tools/studio/index.html">Android Studio 2.0</a>, or
+ later.
+ </li>
-<h2>You Should Also Read</h2>
-<ul>
-<li><a href="{@docRoot}tools/testing/testing_android.html">Testing Concepts</a></li>
-<li><a href="https://github.com/googlesamples/android-testing"
- class="external-link">Android Testing Samples</a></li>
-<li><a href="{@docRoot}about/dashboards/index.html">Android Dashboards</a></li>
-</ul>
+ <li>The Android Support Repository (available from the <a href=
+ "{@docRoot}tools/help/sdk-manager.html">SDK Manager</a>)
+ </li>
+ </ul>
-</div>
+ <h2>
+ This lesson teaches you to
+ </h2>
+
+ <ol>
+ <li>
+ <a href="#config-local-tests">Configure Your Project for Local Unit
+ Tests</a>
+ </li>
+
+ <li>
+ <a href="#config-instrumented-tests">Configure Your Project for
+ Instrumented Tests</a>
+ </li>
+
+ <li>
+ <a href="#build">Build and Run Your Tests</a>
+ <ol>
+ <li>
+ <a href="#run-local-tests">Run Local Unit Tests</a>
+ </li>
+
+ <li>
+ <a href="#run-instrumented-tests">Run Instrumented Tests</a>
+ </li>
+
+ <li>
+ <a href="#run-ctl">Run Instrumented Tests with Cloud Test Lab</a>
+ </li>
+ </ol>
+ </li>
+ </ol>
+
+ <h2>
+ See also
+ </h2>
+
+ <ul>
+ <li>
+ <a href="{@docRoot}tools/testing/testing_android.html">Testing
+ Concepts</a>
+ </li>
+
+ <li>
+ <a href="https://github.com/googlesamples/android-testing" class=
+ "external-link">Android Testing Samples</a>
+ </li>
+
+ <li>
+ <a href="https://developers.google.com/cloud-test-lab/">Cloud Test
+ Lab</a>
+ </li>
+ </ul>
+ </div>
</div>
-<p>You should be writing and running tests as part of your Android app development cycle.
-Well-written tests can help you catch bugs early in development and give you confidence in your
-code.</p>
+<p>
+ Writing and running tests are important parts of the Android app development
+ cycle. Well-written tests can help you catch bugs early in development and
+ give you confidence in your code. Using Android Studio, you can run local
+ unit tests or instrumented tests on a variety of physical or virtual Android
+ devices. You can then analyze the results and make changes to your code
+ without leaving the development environment.
+</p>
-<p>To verify specific behavior in your app, and to check for consistency across different Android
-devices, you can write a <a href="//en.wikipedia.org/wiki/Test_case"
-class="external-link">test case</a>. This lesson teaches you how to build a test case using the
-JUnit 4 framework and the testing APIs and tools provided by Google, and how to run your
-tests.</p>
+<p>
+ <em>Local unit tests</em> are tests that run on your local machine, without
+ needing access to the Android framework or an Android device. To learn how to
+ develop local units tests, see <a href=
+ "{@docRoot}training/testing/unit-testing/local-unit-tests.html">Building
+ Local Unit Tests</a>.
+</p>
-<h2 id="setup">Set Up Your Testing Environment</h2>
+<p>
+ <em>Instrumented tests</em> are tests that run on an Android device or
+ emulator. These tests have access to {@link android.app.Instrumentation}
+ information, such as the {@link android.content.Context} for the app under
+ test. Instrumented tests can be used for unit, user interface (UI), or app
+ component integration testing. To learn how to develop instrumented tests for
+ your specific needs, see these additional topics:
+</p>
-<p>Before you start writing and running your tests, you must set up your test
-development environment. Android Studio provides an integrated development environment for you to
-create, build, and run Android app test cases from a graphical user interface (GUI).</p>
-
-<p>You must first download the prerequisite Android development tools before proceeding:
<ul>
-<li><a href="{@docRoot}sdk/index.html">Android Studio</a> (latest version).</li>
-<li>The latest Android Support Repository using the
- <a href="{@docRoot}tools/help/sdk-manager.html">SDK Manager</a>. </li>
+ <li>
+ <a href=
+ "{@docRoot}training/testing/unit-testing/instrumented-unit-tests.html">Building
+ Instrumented Unit Tests</a> - Build more complex unit tests that have
+ Android dependencies which cannot be easily filled by using mock objects.
+ </li>
+
+ <li>
+ <a href="{@docRoot}training/testing/ui-testing/index.html">Automating User
+ Interface Tests</a> - Create tests to verify that the user interface
+ behaves correctly for user interactions within a single app or for
+ interactions across multiple apps.
+ </li>
+
+ <li>
+ <a href="{@docRoot}training/testing/integration-testing/index.html">Testing
+ App Component Integrations</a> - Verify the behavior of components that
+ users do not directly interact with, such as a <a href=
+ "{@docRoot}guide/components/services.html">Service</a> or a <a href=
+ "guide/topics/providers/content-providers.html">Content Provider</a>.
+ </li>
</ul>
-<p>Based on the type of test you want to create, configure the test code source location and the
- project dependencies in Android Studio as described in the following sections.</p>
+<p>
+ This lesson teaches you how to build and run your tests using using Android
+ Studio. If you are not using Android Studio, you can learn how to
+ <a href="{@docRoot}tools/testing/testing_otheride.html">run your tests from
+ the command-line</a>.
+</p>
-<h3 id="config-local-tests">Configure Your Project for Local Unit Tests</h3>
-<p><em>Local unit tests</em> are tests that run on your local machine, without needing access to the
-Android framework or an Android device. To learn how to develop local units tests, see
-<a href="{@docRoot}training/testing/unit-testing/local-unit-tests.html">
-Building Local Unit Tests</a>.</p>
-<p>In your Android Studio project, you must store the source files for local unit tests under a
-specific source directory ({@code src/test/java}). This feature improves your project organization
-by letting you group your unit tests together into a single source set.</p>
-<p>As with production code, you can create local unit tests for a
-<a href="http://developer.android.com/tools/building/configuring-gradle.html#workBuildVariants"
-class="external-link">specific flavor or build type</a>. Keep your unit tests in a test
-source tree location that corresponds to your production source tree, such as:</p>
+<h3 id="config-local-tests">
+ Configure Your Project for Local Unit Tests
+</h3>
+
+<p>
+ In your Android Studio project, you must store the source files for local
+ unit tests under a specific source directory ({@code src/test/java}). This
+ improves project organization by grouping your unit tests together into a
+ single source set.
+</p>
+
+<p>
+ As with production code, you can create local unit tests for a <a href=
+ "{@docRoot}tools/building/configuring-gradle.html#workBuildVariants">specific
+ flavor or build type</a>. Keep your unit tests in a test source tree location
+ that corresponds to your production source tree, such as:
+</p>
<table>
<tr>
@@ -89,15 +173,21 @@
</tr>
</table>
-<p>You'll need to configure the testing dependencies for your project to use the
- standard APIs provided by the JUnit 4 framework. To simplify your local unit test development,
- we recommend that you include the <a href="https://github.com/mockito/mockito"
- class="external-link">Mockito</a> library if your test needs to interact with Android
- dependencies. To learn more about using mock objects in your local unit tests, see
-<a href="{@docRoot}training/testing/unit-testing/local-unit-tests.html#mocking-dependencies">
- Mocking Android dependencies</a>.</p>
-<p>In the {@code build.gradle} file of your Android app module, specify your dependencies like
-this:</p>
+<p>
+ You'll need to configure the testing dependencies for your project to use the
+ standard APIs provided by the JUnit 4 framework. If your test needs to
+ interact with Android dependencies, include the <a href=
+ "https://github.com/mockito/mockito" class="external-link">Mockito</a>
+ library to simplify your local unit tests. To learn more about using mock
+ objects in your local unit tests, see <a href=
+ "{@docRoot}training/testing/unit-testing/local-unit-tests.html#mocking-dependencies">
+ Mocking Android dependencies</a>.
+</p>
+
+<p>
+ In your app's top-level {@code build.gradle} file, you need to specify these
+ libraries as dependencies:
+</p>
<pre>
dependencies {
@@ -108,46 +198,43 @@
}
</pre>
-<h3 id="config-instrumented-tests">Configure Your Project for Instrumented Tests</h3>
-<p><em>Instrumented tests</em> are tests that run on an Android device or emulator. These tests
-have access to {@link android.app.Instrumentation} information, such as the
-{@link android.content.Context} for the app under test. Instrumented tests can be used for unit,
-user interface (UI), or app component integration testing. To learn how to develop instrumented
-tests for your specific needs, see these additional topics:
-<ul>
-<li><a href="{@docRoot}training/testing/unit-testing/instrumented-unit-tests.html">
- Building Instrumented Unit Tests</a> - Build more complex unit tests that have Android
- dependencies which cannot be easily filled by using mock objects.</li>
-<li><a href="{@docRoot}training/testing/ui-testing/index.html">
- Automating User Interface Tests</a> - Create tests to verify that the user interface behaves
- correctly for user interactions within a single app or for interactions across multiple apps.</li>
-<li><a href="{@docRoot}training/testing/integration-testing/index.html">
- Testing App Component Integrations</a> - Verify the behavior of components that users do not
-directly interact with, such as a <a href="{@docRoot}guide/components/services.html">Service</a> or
-a <a href="guide/topics/providers/content-providers.html">Content Provider</a>.</li>
-</ul>
-</p>
+<h3 id="config-instrumented-tests">
+ Configure Your Project for Instrumented Tests
+</h3>
+
<p>
-In your Android Studio project, you must place the source code for your instrumentated tests under
-a specific directory (<code>src/androidTest/java</code>).
+ In your Android Studio project, you must place the source code for your
+ instrumentated tests under a specific directory
+ (<code>src/androidTest/java</code>).
</p>
+
<p>
-Download the Android Testing Support Library, which provides APIs that allow you to quickly build and
-run instrumented test code for your apps. The Testing Support Library includes a JUnit 4 test runner
-(<a href="{@docRoot}tools/testing-support-library/index.html#AndroidJUnitRunner">AndroidJUnitRunner
-</a>) and APIs for functional UI tests
-(<a href="{@docRoot}tools/testing-support-library/index.html#Espresso">Espresso</a> and
-<a href="{@docRoot}tools/testing-support-library/index.html#UIAutomator">UI Automator</a>). To
-learn how to install the library, see
-<a href="{@docRoot}tools/testing-support-library/index.html#setup">Testing Support Library Setup</a>.
+ <a href="{@docRoot}tools/testing-support-library/index.html#setup">Download
+ the Android Testing Support Library Setup</a>, which provides APIs that allow
+ you to quickly build and run instrumented test code for your apps. The
+ Testing Support Library includes a JUnit 4 test runner (<a href=
+ "{@docRoot}tools/testing-support-library/index.html#AndroidJUnitRunner">AndroidJUnitRunner</a>
+ ) and APIs for functional UI tests (<a href=
+ "{@docRoot}tools/testing-support-library/index.html#Espresso">Espresso</a>
+ and <a href=
+ "{@docRoot}tools/testing-support-library/index.html#UIAutomator">UI
+ Automator</a>).
</p>
-<p>You'll need to configure the Android testing dependencies for your project to use the test runner
-and the rules APIs provided by the Testing Support Library. To simplify your test development,
-we also recommend that you include the <a href="https://github.com/hamcrest"
-class="external-link">Hamcrest</a> library, which lets you create more flexible assertions using the
-Hamcrest matcher APIs.</p>
-<p>In the {@code build.gradle} file of your Android app module, specify your dependencies like
-this:</p>
+
+<p>
+ You'll need to configure the Android testing dependencies for your project to
+ use the test runner and the rules APIs provided by the Testing Support
+ Library. To simplify your test development, we also recommend that you
+ include the <a href="https://github.com/hamcrest" class=
+ "external-link">Hamcrest</a> library, which lets you create more flexible
+ assertions using the Hamcrest matcher APIs.
+</p>
+
+<p>
+ In your app's top-level {@code build.gradle} file, you need to specify these
+ libraries as dependencies:
+</p>
+
<pre>
dependencies {
androidTestCompile 'com.android.support:support-annotations:23.0.1'
@@ -162,59 +249,13 @@
}
</pre>
-<h2 id="build">Build and Run Your Tests</h2>
-
-<p>You can run build and run your tests in a similar way to how you run your Android apps --
- graphically in Android Studio or from the command-line using the
-<a href="{@docRoot}tools/building/plugin-for-gradle.html">
-Android Plugin for Gradle</a>.</p>
-
-<h3 id="run-local-tests">Run Local Unit Tests</h3>
<p>
-The Android Plugin for Gradle compiles the local unit test code located in the default directory
-({@code src/test/java}), builds a test app, and executes it locally
-using the default test runner class.
+ To use JUnit 4 test classes, make sure to specify <a href=
+ "{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code
+ AndroidJUnitRunner}</a> as the default test instrumentation runner in your
+ project by including the following setting in your app's module-level {@code build.gradle}
+ file:
</p>
-<p>
-To run local unit tests in your Gradle project from Android Studio:
-</p>
-<ol>
-<li>In the <strong>Project</strong> window, right click on the project and synchronize your project.
-</li>
-<li>Open the <strong>Build Variants</strong> window by clicking the left-hand tab, then change the
-test artifact to <em>Unit Tests</em>.
-</li>
-<li>In the <strong>Project</strong> window, drill down to your unit test class or method,
-then right-click and run it. To run all tests in the unit test directory, select the directory then
-right-click and press <strong>Run tests</strong>.
-</li>
-</ol>
-
-<p>Android Studio displays the results of the unit test execution in the <strong>Run</strong>
-window.</p>
-
-<p>To run local unit tests in your Gradle project from the command-line, call the {@code test} task
-command.</p>
-
-<pre>
-./gradlew test
-</pre>
-
-<p>If there are failing tests, the command will display links to HTML reports (one per build
-variant). You can find the generated HTML test result reports in the
-{@code <path_to_your_project>/app/build/reports/tests/} directory, and the corresponding XML
-files in the {@code <path_to_your_project>/app/build/test-results/} directory.</p>
-
-<h3 id="run-instrumented-tests">Run Instrumented Tests</h3>
-<p>
-The Android Plugin for Gradle compiles the instrumented test code located in the default directory
-({@code src/androidTest/java}), builds a test APK and production APK, installs both APKs on the
-connected device or emulator, and executes the tests.</p>
-
-<p>Make sure to specify
-<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
-{@code AndroidJUnitRunner}</a> as the default test instrumentation runner in your project. To do
-this, add the following setting in your {@code build.gradle} file:</p>
<pre>
android {
@@ -224,29 +265,257 @@
}
</pre>
-<p>To run your instrumented tests in Android Studio:</p>
+<h2 id="build">
+ Build and Run Your Tests
+</h2>
+
+<p>
+ Android Studio provides all the tools you need to build, run, and analyze
+ your tests within the development environment. You can also run instrumented
+ tests on multiple device configurations, simultaneously, using <a href=
+ "https://developers.google.com/cloud-test-lab/">Cloud Test Lab</a>
+ integration.
+</p>
+
+<p class="note">
+ <strong>Note:</strong> While running or debugging instrumented tests,
+ Android Studio does not inject the additional methods required for <a href=
+ "{@docRoot}tools/building/building-studio.html#instant-run">Instant Run</a>
+ and turns the feature off.
+</p>
+
+<h3 id="run-local-tests">
+ Run Local Unit Tests
+</h3>
+
+<p>
+ To run your local unit tests:
+</p>
+
<ol>
-<li>Open the <strong>Build Variants</strong> window by clicking the left-hand tab, then set the
-test artifact to <em>Android Instrumentation Tests</em>.
-</li>
-<li>In the <strong>Project</strong> window, drill down to your instrumented test class or method,
- then right-click and run it using the Android Test configuration. To run all tests in the
-instrumented test directory, select the directory then right-click and press
-<strong>Run tests</strong>.
-</li>
+ <li>In the <em>Project</em> window, right click on the project and
+ synchronize your project.
+ </li>
+
+ <li>Open the <em>Build Variants</em> window by clicking the left-hand tab,
+ then change the test artifact to <em>Unit Tests</em>.
+ </li>
+
+ <li>In the <em>Project</em> window, navigate to your unit test class or
+ method, then right-click it and select <strong>Run</strong> <img src=
+ "{@docRoot}images/tools/as-run.png" alt="" style=
+ "vertical-align:bottom;margin:0;">.
+ <ul>
+ <li>To run all tests in the unit test directory, right-click on the
+ directory and select <strong>Run tests</strong> <img src=
+ "{@docRoot}images/tools/as-run.png" alt="" style=
+ "vertical-align:bottom;margin:0;">.
+ </li>
+ </ul>
+ </li>
</ol>
-<p>Android Studio displays the results of the instrumented test execution in the
-<strong>Run</strong> window.</p>
+<p>
+ The Android Plugin for Gradle compiles the local unit test code located in
+ the default directory ({@code src/test/java}), builds a test app, and
+ executes it locally using the default test runner class. Android Studio then
+ displays the results in the <em>Run</em> window.
+</p>
-<p>To run your instrumented tests from the command-line via Gradle, call the
- {@code connectedAndroidTest} (or {@code cAT}) task:</p>
+<h3 id="run-instrumented-tests">
+ Run Instrumented Tests
+</h3>
-<pre>
-./gradlew cAT
-</pre>
+<p>
+ To run your instrumented tests:
+</p>
-<p>You can find the generated HTML test result reports in the
-{@code <path_to_your_project>/app/build/outputs/reports/androidTests/connected/} directory,
-and the corresponding XML files in the
-{@code <path_to_your_project>/app/build/outputs/androidTest-results/connected/} directory.</p>
\ No newline at end of file
+<ol>
+ <li>Open the <em>Build Variants</em> window by clicking the left-hand tab,
+ then set the test artifact to <em>Android Instrumentation Tests</em>.
+ </li>
+
+ <li>In the <em>Project</em> window, navigate to your instrumented test class
+ or method, then right-click and run it using the Android Test configuration.
+ To run all tests in the instrumented test directory, right-click the
+ directory and select <strong>Run tests</strong> <img src=
+ "{@docRoot}images/tools/as-run.png" alt="" style=
+ "vertical-align:bottom;margin:0;">.
+ </li>
+</ol>
+
+<p>
+ The <a href="{@docRoot}tools/building/plugin-for-gradle.html">Android Plugin
+ for Gradle</a> compiles the instrumented test code located in the default
+ directory ({@code src/androidTest/java}), builds a test APK and production
+ APK, installs both APKs on the connected device or emulator, and runs the
+ tests. Android Studio then displays the results of the instrumented test execution in the
+ <em>Run</em> window.
+</p>
+
+<h3 id="run-ctl">Run Instrumented Tests with Cloud Test Lab</h3>
+
+<p>
+ Using <a href="https://developers.google.com/cloud-test-lab/">Cloud Test
+ Lab</a>, you can simultaneously test your app on many popular Android
+ devices, across multiple languages, screen orientations, and versions of the
+ Android platform. These tests run on actual physical devices in remote Google
+ data centers. You can also <a href=
+ "https://developers.google.com/cloud-test-lab/test-screenshots">configure
+ your instrumented tests to take screenshots</a> while Cloud Test Lab runs its
+ tests. You can <a href=
+ "https://developers.google.com/cloud-test-lab/command-line">deploy tests to
+ Cloud Test Lab from the command line</a>, or from Android Studio's integrated
+ testing tools.
+</p>
+
+<p>
+ Android Studio allows you to connect to your Google Cloud Platform account,
+ configure your tests, deploy them to Cloud Test Lab, and analyze the results
+ all within the development environment. Cloud Test Lab in Android Studio
+ supports the following Android test frameworks: <a href=
+ "{@docRoot}training/testing/ui-testing/espresso-testing.html">Espresso</a>,
+ <a href="{@docRoot}tools/testing-support-library/index.html#UIAutomator">UI
+ Automator 2.0</a>, or <a class="external-link" href=
+ "https://github.com/robotiumtech/robotium">Robotium</a>. Test results provide
+ test logs and include the details of any app failures.
+</p>
+
+<p>
+ Before you can start using Cloud Test Lab, you need to:
+</p>
+
+<ol>
+ <li>
+ <a href="https://console.developers.google.com/freetrial">Create a
+ Google Cloud Platform account</a> to use with active billing.
+ </li>
+
+ <li>
+ <a href="https://support.google.com/cloud/answer/6251787">Create a Google
+ Cloud project</a> for your app.
+ </li>
+
+ <li>
+ <a href="https://support.google.com/cloud/answer/6288653">Set up an active
+ billing account</a> and associate it with the project you just created.
+ </li>
+</ol>
+
+<h4 id="configure-matrix">
+Configure a test matrix and run a test
+</h4>
+
+<p>
+ Android Studio provides integrated tools that allow you to configure how you
+ want to deploy your tests to Cloud Test Lab. After you have created a Google
+ Cloud project with active billing, you can create a test configuration and
+ run your tests:
+</p>
+
+<ol>
+ <li>Click <strong>Run</strong> > <strong>Edit Configurations</strong> from
+ the main menu.
+ </li>
+
+ <li>Click <strong>Add New Configuration (+)</strong> and select
+ <strong>Android Tests</strong>.
+ </li>
+
+ <li>In the Android Test configuration dialog:
+ <ol type="a">
+ <li>Enter or select the details of your test, such as the test name, module
+ type, test type, and test class.
+ </li>
+
+ <li>From the <em>Target</em> drop-down menu under <em>Deployment Target
+ Options</em>, select <strong>Cloud Test Lab Device Matrix</strong>.
+ </li>
+
+ <li>If you are not logged in, click <strong>Connect to Google Cloud
+ Platform</strong> and allow Android Studio access to your account.
+ </li>
+
+ <li>Next to <em>Cloud Project</em>, click the <img src=
+ "{@docRoot}images/tools/as-wrench.png" alt="wrench and nut" style=
+ "vertical-align:bottom;margin:0;"> button and select your Google Cloud
+ Platform project from the list.
+ </li>
+ </ol>
+ </li>
+
+ <li>Create and configure a test matrix:
+ <ol type="a">
+ <li>Next to the <em>Matrix Configuration</em> drop-down list, click <strong>
+ Open Dialog</strong> <img src="{@docRoot}images/tools/as-launchavdm.png"
+ alt="ellipses button" style="vertical-align:bottom;margin:0;">.
+ </li>
+
+ <li>Click <strong>Add New Configuration (+)</strong>.
+ </li>
+
+ <li>In the <strong>Name</strong> field, enter a name for your new
+ configuration.
+ </li>
+
+ <li>Select the device(s), Android version(s), locale(s) and screen
+ orientation(s) that you want to test your app with. Cloud Test Lab will test
+ your app against every combination of your selections when generating test
+ results.
+ </li>
+
+ <li>Click <strong>OK</strong> to save your configuration.
+ </li>
+ </ol>
+ </li>
+
+ <li>Click <strong>OK</strong> in the <em>Run/Debug Configurations</em> dialog
+ to exit.
+ </li>
+
+ <li>Run your tests by clicking <strong>Run</strong> <img src=
+ "{@docRoot}images/tools/as-run.png" alt="" style=
+ "vertical-align:bottom;margin:0;">.
+ </li>
+</ol>
+
+<h4 id="ctl-results">
+ Analyzing test results
+</h4>
+
+<p>
+ When Cloud Test Lab completes running your tests, the <em>Run</em> window will
+ open to show the results, as shown in figure 1. You may need to click
+ <strong>Show Passed</strong> <img src="{@docRoot}images/tools/as-ok.png" alt=
+ "" style="vertical-align:bottom;margin:0;"> to see all your executed tests.
+</p>
+
+<p>
+ <img src="{@docRoot}images/training/ctl-test-results.png" alt="">
+</p>
+
+<p class="img-caption">
+ <strong>Figure 1.</strong> Viewing the results of instrumented tests using
+ Cloud Test Lab.
+</p>
+
+<p>
+ You can also analyze your tests on the web by following the link displayed at
+ the beginning of the test execution log in the <em>Run</em> window, as shown
+ in figure 2.
+</p>
+
+<p>
+ <img src="{@docRoot}images/training/ctl-exec-log.png" alt="">
+</p>
+
+<p class="img-caption">
+ <strong>Figure 2.</strong> Click the link to view detailed test results on
+ the web.
+</p>
+
+<p>
+ To learn more about interpreting web results, see <a href=
+ "https://developers.google.com/cloud-test-lab/analyzing-results">Analyzing
+ Cloud Test Lab Web Results</a>.
+</p>
\ No newline at end of file
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index af99f79..c65880b 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1266,7 +1266,7 @@
/**
* @hide
*/
- protected static void throwIfCannotDraw(Bitmap bitmap) {
+ protected void throwIfCannotDraw(Bitmap bitmap) {
if (bitmap.isRecycled()) {
throw new RuntimeException("Canvas: trying to use a recycled bitmap " + bitmap);
}
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 5fb8425..8251ee6 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -344,7 +344,8 @@
const SkPaint& paint, int vertexBufferRenderFlags) {
if (CC_LIKELY(vertexBuffer.getVertexCount())) {
bool shadowInterp = vertexBufferRenderFlags & VertexBufferRenderFlags::ShadowInterp;
- const int transformFlags = TransformFlags::OffsetByFudgeFactor;
+ const int transformFlags = vertexBufferRenderFlags & VertexBufferRenderFlags::Offset
+ ? TransformFlags::OffsetByFudgeFactor : 0;
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
.setRoundRectClipState(state.roundRectClipState)
diff --git a/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
index 5471486..781f88c 100644
--- a/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
+++ b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
@@ -109,3 +109,37 @@
EXPECT_FLOAT_EQ(128 / 255.0f, glop.fill.color.a) << "Rect quad should use op alpha";
});
}
+
+static int getGlopTransformFlags(renderthread::RenderThread& renderThread, RecordedOp* op) {
+ int result = 0;
+ testUnmergedGlopDispatch(renderThread, op, [&result] (const Glop& glop) {
+ result = glop.transform.transformFlags;
+ });
+ return result;
+}
+
+RENDERTHREAD_TEST(BakedOpDispatcher, offsetFlags) {
+ Rect bounds(10, 15, 20, 25);
+ SkPaint paint;
+ SkPaint aaPaint;
+ aaPaint.setAntiAlias(true);
+
+ RoundRectOp roundRectOp(bounds, Matrix4::identity(), nullptr, &paint, 0, 270);
+ EXPECT_EQ(TransformFlags::None, getGlopTransformFlags(renderThread, &roundRectOp))
+ << "Expect no offset for round rect op.";
+
+ const float points[4] = {0.5, 0.5, 1.0, 1.0};
+ PointsOp antiAliasedPointsOp(bounds, Matrix4::identity(), nullptr, &aaPaint, points, 4);
+ EXPECT_EQ(TransformFlags::None, getGlopTransformFlags(renderThread, &antiAliasedPointsOp))
+ << "Expect no offset for AA points.";
+ PointsOp pointsOp(bounds, Matrix4::identity(), nullptr, &paint, points, 4);
+ EXPECT_EQ(TransformFlags::OffsetByFudgeFactor, getGlopTransformFlags(renderThread, &pointsOp))
+ << "Expect an offset for non-AA points.";
+
+ LinesOp antiAliasedLinesOp(bounds, Matrix4::identity(), nullptr, &aaPaint, points, 4);
+ EXPECT_EQ(TransformFlags::None, getGlopTransformFlags(renderThread, &antiAliasedLinesOp))
+ << "Expect no offset for AA lines.";
+ LinesOp linesOp(bounds, Matrix4::identity(), nullptr, &paint, points, 4);
+ EXPECT_EQ(TransformFlags::OffsetByFudgeFactor, getGlopTransformFlags(renderThread, &linesOp))
+ << "Expect an offset for non-AA lines.";
+}
\ No newline at end of file
diff --git a/packages/DocumentsUI/res/values-night/colors.xml b/packages/DocumentsUI/res/values-night/colors.xml
deleted file mode 100644
index f77017d..0000000
--- a/packages/DocumentsUI/res/values-night/colors.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
- <color name="directory_background">#ff111111</color>
- <color name="item_doc_grid_protect_background">#88ffffff</color>
-</resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 44d7136..50273af 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -32,6 +32,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
+import android.database.ContentObserver;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -46,7 +47,6 @@
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.WindowManager;
import android.widget.Spinner;
import com.android.documentsui.SearchViewManager.SearchManagerListener;
@@ -78,6 +78,12 @@
List<EventListener> mEventListeners = new ArrayList<>();
private final String mTag;
+ private final ContentObserver mRootsCacheObserver = new ContentObserver(new Handler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ new HandleRootsChangedTask(BaseActivity.this).execute(getCurrentRoot());
+ }
+ };
@LayoutRes
private int mLayoutId;
@@ -118,14 +124,8 @@
mRoots = DocumentsApplication.getRootsCache(this);
- mRoots.setOnCacheUpdateListener(
- new RootsCache.OnCacheUpdateListener() {
- @Override
- public void onCacheUpdate() {
- new HandleRootsChangedTask(BaseActivity.this)
- .execute(getCurrentRoot());
- }
- });
+ getContentResolver().registerContentObserver(
+ RootsCache.sNotificationUri, false, mRootsCacheObserver);
mSearchManager = new SearchViewManager(this, icicle);
@@ -190,7 +190,7 @@
@Override
protected void onDestroy() {
- mRoots.setOnCacheUpdateListener(null);
+ getContentResolver().unregisterContentObserver(mRootsCacheObserver);
super.onDestroy();
}
@@ -793,6 +793,7 @@
private static final class HandleRootsChangedTask
extends PairedTask<BaseActivity, RootInfo, RootInfo> {
+ RootInfo mCurrentRoot;
DocumentInfo mDefaultRootDocument;
public HandleRootsChangedTask(BaseActivity activity) {
@@ -802,11 +803,10 @@
@Override
protected RootInfo run(RootInfo... roots) {
assert(roots.length == 1);
-
- final RootInfo currentRoot = roots[0];
+ mCurrentRoot = roots[0];
final Collection<RootInfo> cachedRoots = mOwner.mRoots.getRootsBlocking();
for (final RootInfo root : cachedRoots) {
- if (root.getUri().equals(currentRoot.getUri())) {
+ if (root.getUri().equals(mCurrentRoot.getUri())) {
// We don't need to change the current root as the current root was not removed.
return null;
}
@@ -827,6 +827,14 @@
return;
}
+ // If the activity has been launched for the specific root and it is removed, finish the
+ // activity.
+ final Uri uri = mOwner.getIntent().getData();
+ if (uri != null && uri.equals(mCurrentRoot.getUri())) {
+ mOwner.finish();
+ return;
+ }
+
// Clear entire backstack and start in new root.
mOwner.mState.onRootChanged(defaultRoot);
mOwner.mSearchManager.update(defaultRoot);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
index c78face..af6aee7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
@@ -101,7 +101,10 @@
}
}
- intent.putExtra(Intent.EXTRA_INDEX, documentLocation);
+ // The documentLocation variable contains an index in "uris". However,
+ // ClipData contains a slice of "uris", so we need to shift the location
+ // so it points to the same Uri.
+ intent.putExtra(Intent.EXTRA_INDEX, documentLocation - range.getLower());
intent.setClipData(clipData);
return intent;
@@ -147,12 +150,12 @@
authority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY);
uri = DocumentsContract.buildDocumentUri(authority, id);
- if (id.equals(mDocument.documentId)) {
- if (DEBUG) Log.d(TAG, "Found starting point for QV. " + i);
- documentLocation = i;
- }
-
uris.add(uri);
+
+ if (id.equals(mDocument.documentId)) {
+ documentLocation = uris.size() - 1; // Position in "uris", not in the model.
+ if (DEBUG) Log.d(TAG, "Found starting point for QV. " + documentLocation);
+ }
}
return documentLocation;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index 559348e..88eeb49 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -67,7 +67,6 @@
private final Context mContext;
private final ContentObserver mObserver;
- private OnCacheUpdateListener mCacheUpdateListener;
private final RootInfo mRecentsRoot;
@@ -119,10 +118,6 @@
}
}
- static interface OnCacheUpdateListener {
- void onCacheUpdate();
- }
-
/**
* Gather roots from all known storage providers.
*/
@@ -280,13 +275,6 @@
return null;
}
- @Override
- protected void onPostExecute(Void result) {
- if (mCacheUpdateListener != null) {
- mCacheUpdateListener.onCacheUpdate();
- }
- }
-
private void handleDocumentsProvider(ProviderInfo info) {
// Ignore stopped packages for now; we might query them
// later during UI interaction.
@@ -445,10 +433,6 @@
}
}
- public void setOnCacheUpdateListener(OnCacheUpdateListener cacheUpdateListener) {
- mCacheUpdateListener = cacheUpdateListener;
- }
-
/**
* Returns the default root for the specified state.
*/
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 07c3cdbc..784d30f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -156,7 +156,8 @@
/**
* Compare two strings against each other using system default collator in a
- * case-insensitive mode.
+ * case-insensitive mode. Clusters strings prefixed with {@link DIR_PREFIX}
+ * before other items.
*/
public static int compareToIgnoreCaseNullable(String lhs, String rhs) {
final boolean leftEmpty = TextUtils.isEmpty(lhs);
@@ -169,14 +170,6 @@
return sCollator.compare(lhs, rhs);
}
- /**
- * Compare two strings against each other using system default collator in a
- * case-insensitive mode.
- */
- public static int compareToIgnoreCase(String lhs, String rhs) {
- return sCollator.compare(lhs, rhs);
- }
-
public static boolean isHardwareKeyboardAvailable(Context context) {
return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index b67f6a2..312acb5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -710,10 +710,10 @@
void onDocumentsReady(List<DocumentInfo> docs) {
Intent intent;
- // Filter out directories - those can't be shared.
+ // Filter out directories and virtual files - those can't be shared.
List<DocumentInfo> docsForSend = new ArrayList<>();
for (DocumentInfo doc: docs) {
- if (!Document.MIME_TYPE_DIR.equals(doc.mimeType)) {
+ if (!doc.isDirectory() && !doc.isVirtualDocument()) {
docsForSend.add(doc);
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
index e2a28ad9a..37daca0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
@@ -20,6 +20,8 @@
import static com.android.documentsui.State.SORT_ORDER_DISPLAY_NAME;
import static com.android.documentsui.State.SORT_ORDER_LAST_MODIFIED;
import static com.android.documentsui.State.SORT_ORDER_SIZE;
+import static com.android.documentsui.model.DocumentInfo.getCursorLong;
+import static com.android.documentsui.model.DocumentInfo.getCursorString;
import android.database.Cursor;
import android.database.MergeCursor;
@@ -48,7 +50,6 @@
@VisibleForTesting
public class Model {
private static final String TAG = "Model";
- private static final String EMPTY = "";
private boolean mIsLoading;
private List<UpdateListener> mUpdateListeners = new ArrayList<>();
@@ -63,13 +64,6 @@
private String mIds[] = new String[0];
private int mSortOrder = SORT_ORDER_DISPLAY_NAME;
- private int mAuthorityIndex = -1;
- private int mDocIdIndex = -1;
- private int mMimeTypeIndex = -1;
- private int mDisplayNameIndex = -1;
- private int mSizeIndex = -1;
- private int mLastModifiedIndex = -1;
-
@Nullable String info;
@Nullable String error;
@Nullable DocumentInfo doc;
@@ -111,14 +105,6 @@
mCursor = result.cursor;
mCursorCount = mCursor.getCount();
mSortOrder = result.sortOrder;
- mAuthorityIndex = mCursor.getColumnIndex(RootCursorWrapper.COLUMN_AUTHORITY);
- assert(mAuthorityIndex != -1);
- mDocIdIndex = mCursor.getColumnIndex(Document.COLUMN_DOCUMENT_ID);
- mMimeTypeIndex = mCursor.getColumnIndex(Document.COLUMN_MIME_TYPE);
- mDisplayNameIndex = mCursor.getColumnIndex(Document.COLUMN_DISPLAY_NAME);
- mLastModifiedIndex = mCursor.getColumnIndex(Document.COLUMN_LAST_MODIFIED);
- mSizeIndex = mCursor.getColumnIndex(Document.COLUMN_SIZE);
-
doc = result.doc;
updateModelData();
@@ -171,23 +157,26 @@
// If the cursor is a merged cursor over multiple authorities, then prefix the ids
// with the authority to avoid collisions.
if (mCursor instanceof MergeCursor) {
- mIds[pos] = getStringOrEmpty(mAuthorityIndex) + "|" + getStringOrEmpty(mDocIdIndex);
+ mIds[pos] = getCursorString(mCursor, RootCursorWrapper.COLUMN_AUTHORITY) + "|" +
+ getCursorString(mCursor, Document.COLUMN_DOCUMENT_ID);
} else {
- mIds[pos] = getStringOrEmpty(mDocIdIndex);
+ mIds[pos] = getCursorString(mCursor, Document.COLUMN_DOCUMENT_ID);
}
- mimeType = getStringOrEmpty(mMimeTypeIndex);
+ mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
isDirs[pos] = Document.MIME_TYPE_DIR.equals(mimeType);
- switch (mSortOrder) {
+ switch(mSortOrder) {
case SORT_ORDER_DISPLAY_NAME:
- displayNames[pos] = getStringOrEmpty(mDisplayNameIndex);
+ final String displayName = getCursorString(
+ mCursor, Document.COLUMN_DISPLAY_NAME);
+ displayNames[pos] = displayName;
break;
case SORT_ORDER_LAST_MODIFIED:
- longValues[pos] = getLastModified();
+ longValues[pos] = getLastModified(mCursor);
break;
case SORT_ORDER_SIZE:
- longValues[pos] = getDocSize();
+ longValues[pos] = getCursorLong(mCursor, Document.COLUMN_SIZE);
break;
}
}
@@ -243,7 +232,7 @@
} else {
final String lhs = pivotValue;
final String rhs = sortKey[mid];
- compare = Shared.compareToIgnoreCase(lhs, rhs);
+ compare = Shared.compareToIgnoreCaseNullable(lhs, rhs);
}
if (compare < 0) {
@@ -364,42 +353,13 @@
}
/**
- * @return Value of the string column, or an empty string if no value, or empty value.
- */
- private String getStringOrEmpty(int columnIndex) {
- if (columnIndex == -1)
- return EMPTY;
- final String result = mCursor.getString(columnIndex);
- return result != null ? result : EMPTY;
- }
-
- /**
* @return Timestamp for the given document. Some docs (e.g. active downloads) have a null
- * or missing timestamp - these will be replaced with MAX_LONG so that such files get sorted to
- * the top when sorting by date.
+ * timestamp - these will be replaced with MAX_LONG so that such files get sorted to the top
+ * when sorting by date.
*/
- private long getLastModified() {
- if (mLastModifiedIndex == -1)
- return Long.MAX_VALUE;
- try {
- final long result = mCursor.getLong(mLastModifiedIndex);
- return result > 0 ? result : Long.MAX_VALUE;
- } catch (NumberFormatException e) {
- return Long.MAX_VALUE;
- }
- }
-
- /**
- * @return Size for the given document. If the size is unknown or invalid, returns 0.
- */
- private long getDocSize() {
- if (mSizeIndex == -1)
- return 0;
- try {
- return mCursor.getLong(mSizeIndex);
- } catch (NumberFormatException e) {
- return 0;
- }
+ long getLastModified(Cursor cursor) {
+ long l = getCursorLong(mCursor, Document.COLUMN_LAST_MODIFIED);
+ return (l == -1) ? Long.MAX_VALUE : l;
}
public @Nullable Cursor getItem(String modelId) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
new file mode 100644
index 0000000..48533fa
--- /dev/null
+++ b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.settings;
+
+import android.os.Bundle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.util.MemoryIntArray;
+import android.util.Slog;
+import android.util.SparseIntArray;
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.IOException;
+
+/**
+ * This class tracks changes for global/secure/system tables on a
+ * per user basis and updates a shared memory region which client
+ * processes can read to determine if their local caches are stale,
+ */
+final class GenerationRegistry {
+ private static final String LOG_TAG = "GenerationTracker";
+
+ private static final boolean DEBUG = false;
+
+ private final Object mLock;
+
+ @GuardedBy("mLock")
+ private final SparseIntArray mKeyToIndexMap = new SparseIntArray();
+
+ @GuardedBy("mLock")
+ private final MemoryIntArray mImpl;
+
+ public GenerationRegistry(Object lock) {
+ mLock = lock;
+ // One for the global table, two for system and secure tables for a
+ // managed profile (managed profile is not included in the max user
+ // count), ten for partially deleted users if users are quickly removed,
+ // and twice max user count for system and secure.
+ final int size = 1 + 2 + 10 + 2 * UserManager.getMaxSupportedUsers();
+ MemoryIntArray impl = null;
+ try {
+ impl = new MemoryIntArray(size, false);
+ } catch (IOException e) {
+ Slog.e(LOG_TAG, "Error creating generation tracker", e);
+ }
+ mImpl = impl;
+ }
+
+ public void incrementGeneration(int key) {
+ synchronized (mLock) {
+ if (mImpl != null) {
+ try {
+ final int index = getKeyIndexLocked(key);
+ if (index >= 0) {
+ final int generation = mImpl.get(index) + 1;
+ mImpl.set(index, generation);
+ }
+ } catch (IOException e) {
+ Slog.e(LOG_TAG, "Error updating generation id", e);
+ }
+ }
+ }
+ }
+
+ public void addGenerationData(Bundle bundle, int key) {
+ synchronized (mLock) {
+ if (mImpl != null) {
+ final int index = getKeyIndexLocked(key);
+ if (index >= 0) {
+ bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY, mImpl);
+ bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Exported index:" + index + " for key:"
+ + SettingsProvider.keyToString(key));
+ }
+ }
+ }
+ }
+ }
+
+ private int getKeyIndexLocked(int key) {
+ int index = mKeyToIndexMap.get(key, -1);
+ if (index < 0) {
+ index = findNextEmptyIndex();
+ if (index >= 0) {
+ try {
+ mImpl.set(index, 1);
+ mKeyToIndexMap.append(key, index);
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Allocated index:" + index + " for key:"
+ + SettingsProvider.keyToString(key));
+ }
+ } catch (IOException e) {
+ Slog.e(LOG_TAG, "Cannot write to generation memory array", e);
+ }
+ } else {
+ Slog.e(LOG_TAG, "Could not allocate generation index");
+ }
+ }
+ return index;
+ }
+
+ public void onUserRemoved(int userId) {
+ synchronized (mLock) {
+ if (mImpl != null && mKeyToIndexMap.size() > 0) {
+ final int secureKey = SettingsProvider.makeKey(
+ SettingsProvider.SETTINGS_TYPE_SECURE, userId);
+ resetSlotForKeyLocked(secureKey);
+
+ final int systemKey = SettingsProvider.makeKey(
+ SettingsProvider.SETTINGS_TYPE_SYSTEM, userId);
+ resetSlotForKeyLocked(systemKey);
+ }
+ }
+ }
+
+ private void resetSlotForKeyLocked(int key) {
+ final int index = mKeyToIndexMap.get(key, -1);
+ if (index >= 0) {
+ mKeyToIndexMap.delete(key);
+ try {
+ mImpl.set(index, 0);
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Freed index:" + index + " for key:"
+ + SettingsProvider.keyToString(key));
+ }
+ } catch (IOException e) {
+ Slog.e(LOG_TAG, "Cannot write to generation memory array", e);
+ }
+ }
+ }
+
+ private int findNextEmptyIndex() {
+ try {
+ final int size = mImpl.size();
+ for (int i = 0; i < size; i++) {
+ if (mImpl.get(i) == 0) {
+ return i;
+ }
+ }
+ } catch (IOException e) {
+ Slog.e(LOG_TAG, "Error reading generation memory array", e);
+ }
+ return -1;
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 8dc247a..bb80636 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -42,6 +42,7 @@
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
+import android.os.Debug;
import android.os.DropBoxManager;
import android.os.Environment;
import android.os.Handler;
@@ -51,9 +52,9 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.SELinux;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.UserManagerInternal;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -64,6 +65,7 @@
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.providers.settings.SettingsState.Setting;
+import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import java.io.File;
@@ -146,8 +148,15 @@
Settings.NameValueTable.VALUE
};
- private static final Bundle NULL_SETTING = Bundle.forPair(Settings.NameValueTable.VALUE, null);
+ public static final int SETTINGS_TYPE_GLOBAL = 0;
+ public static final int SETTINGS_TYPE_SYSTEM = 1;
+ public static final int SETTINGS_TYPE_SECURE = 2;
+ public static final int SETTINGS_TYPE_MASK = 0xF0000000;
+ public static final int SETTINGS_TYPE_SHIFT = 28;
+
+ private static final Bundle NULL_SETTING_BUNDLE = Bundle.forPair(
+ Settings.NameValueTable.VALUE, null);
// Per user secure settings that moved to the for all users global settings.
static final Set<String> sSecureMovedToGlobalSettings = new ArraySet<>();
@@ -196,6 +205,40 @@
// We have to call in the package manager with no lock held,
private volatile IPackageManager mPackageManager;
+ public static int makeKey(int type, int userId) {
+ return (type << SETTINGS_TYPE_SHIFT) | userId;
+ }
+
+ public static int getTypeFromKey(int key) {
+ return key >>> SETTINGS_TYPE_SHIFT;
+ }
+
+ public static int getUserIdFromKey(int key) {
+ return key & ~SETTINGS_TYPE_MASK;
+ }
+
+ public static String settingTypeToString(int type) {
+ switch (type) {
+ case SETTINGS_TYPE_GLOBAL: {
+ return "SETTINGS_GLOBAL";
+ }
+ case SETTINGS_TYPE_SECURE: {
+ return "SETTINGS_SECURE";
+ }
+ case SETTINGS_TYPE_SYSTEM: {
+ return "SETTINGS_SYSTEM";
+ }
+ default: {
+ return "UNKNOWN";
+ }
+ }
+ }
+
+ public static String keyToString(int key) {
+ return "Key[user=" + getUserIdFromKey(key) + ";type="
+ + settingTypeToString(getTypeFromKey(key)) + "]";
+ }
+
@Override
public boolean onCreate() {
synchronized (mLock) {
@@ -204,6 +247,7 @@
mSettingsRegistry = new SettingsRegistry();
}
registerBroadcastReceivers();
+ startWatchingUserRestrictionChanges();
return true;
}
@@ -213,28 +257,28 @@
switch (method) {
case Settings.CALL_METHOD_GET_GLOBAL: {
Setting setting = getGlobalSetting(name);
- return packageValueForCallResult(setting);
+ return packageValueForCallResult(setting, isTrackingGeneration(args));
}
case Settings.CALL_METHOD_GET_SECURE: {
Setting setting = getSecureSetting(name, requestingUserId);
- return packageValueForCallResult(setting);
+ return packageValueForCallResult(setting, isTrackingGeneration(args));
}
case Settings.CALL_METHOD_GET_SYSTEM: {
Setting setting = getSystemSetting(name, requestingUserId);
- return packageValueForCallResult(setting);
+ return packageValueForCallResult(setting, isTrackingGeneration(args));
}
case Settings.CALL_METHOD_PUT_GLOBAL: {
String value = getSettingValue(args);
- insertGlobalSetting(name, value, requestingUserId);
+ insertGlobalSetting(name, value, requestingUserId, false);
break;
}
case Settings.CALL_METHOD_PUT_SECURE: {
String value = getSettingValue(args);
- insertSecureSetting(name, value, requestingUserId);
+ insertSecureSetting(name, value, requestingUserId, false);
break;
}
@@ -335,13 +379,13 @@
switch (table) {
case TABLE_GLOBAL: {
- if (insertGlobalSetting(name, value, UserHandle.getCallingUserId())) {
+ if (insertGlobalSetting(name, value, UserHandle.getCallingUserId(), false)) {
return Uri.withAppendedPath(Settings.Global.CONTENT_URI, name);
}
} break;
case TABLE_SECURE: {
- if (insertSecureSetting(name, value, UserHandle.getCallingUserId())) {
+ if (insertSecureSetting(name, value, UserHandle.getCallingUserId(), false)) {
return Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
}
} break;
@@ -398,12 +442,12 @@
switch (args.table) {
case TABLE_GLOBAL: {
final int userId = UserHandle.getCallingUserId();
- return deleteGlobalSetting(args.name, userId) ? 1 : 0;
+ return deleteGlobalSetting(args.name, userId, false) ? 1 : 0;
}
case TABLE_SECURE: {
final int userId = UserHandle.getCallingUserId();
- return deleteSecureSetting(args.name, userId) ? 1 : 0;
+ return deleteSecureSetting(args.name, userId, false) ? 1 : 0;
}
case TABLE_SYSTEM: {
@@ -439,12 +483,12 @@
switch (args.table) {
case TABLE_GLOBAL: {
final int userId = UserHandle.getCallingUserId();
- return updateGlobalSetting(args.name, value, userId) ? 1 : 0;
+ return updateGlobalSetting(args.name, value, userId, false) ? 1 : 0;
}
case TABLE_SECURE: {
final int userId = UserHandle.getCallingUserId();
- return updateSecureSetting(args.name, value, userId) ? 1 : 0;
+ return updateSecureSetting(args.name, value, userId, false) ? 1 : 0;
}
case TABLE_SYSTEM: {
@@ -557,11 +601,15 @@
switch (intent.getAction()) {
case Intent.ACTION_USER_REMOVED: {
- mSettingsRegistry.removeUserStateLocked(userId, true);
+ synchronized (mLock) {
+ mSettingsRegistry.removeUserStateLocked(userId, true);
+ }
} break;
case Intent.ACTION_USER_STOPPED: {
- mSettingsRegistry.removeUserStateLocked(userId, false);
+ synchronized (mLock) {
+ mSettingsRegistry.removeUserStateLocked(userId, false);
+ }
} break;
}
}
@@ -582,6 +630,92 @@
UserHandle.ALL, true);
}
+ private void startWatchingUserRestrictionChanges() {
+ // TODO: The current design of settings looking different based on user restrictions
+ // should be reworked to keep them separate and system code should check the setting
+ // first followed by checking the user restriction before performing an operation.
+ UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class);
+ userManager.addUserRestrictionsListener((int userId, Bundle newRestrictions,
+ Bundle prevRestrictions) -> {
+ // We are changing the settings affected by restrictions to their current
+ // value with a forced update to ensure that all cross profile dependencies
+ // are taken into account. Also make sure the settings update to.. the same
+ // value passes the security checks, so clear binder calling id.
+ if (newRestrictions.containsKey(UserManager.DISALLOW_SHARE_LOCATION)
+ != prevRestrictions.containsKey(UserManager.DISALLOW_SHARE_LOCATION)) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ Setting setting = getSecureSetting(
+ Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
+ updateSecureSetting(Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+ setting != null ? setting.getValue() : null, userId, true);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ if (newRestrictions.containsKey(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)
+ != prevRestrictions.containsKey(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ Setting setting = getGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS);
+ updateGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS,
+ setting != null ? setting.getValue() : null, userId, true);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ if (newRestrictions.containsKey(UserManager.DISALLOW_DEBUGGING_FEATURES)
+ != prevRestrictions.containsKey(UserManager.DISALLOW_DEBUGGING_FEATURES)) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ Setting setting = getGlobalSetting(Settings.Global.ADB_ENABLED);
+ updateGlobalSetting(Settings.Global.ADB_ENABLED,
+ setting != null ? setting.getValue() : null, userId, true);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ if (newRestrictions.containsKey(UserManager.ENSURE_VERIFY_APPS)
+ != prevRestrictions.containsKey(UserManager.ENSURE_VERIFY_APPS)) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ Setting enable = getGlobalSetting(
+ Settings.Global.PACKAGE_VERIFIER_ENABLE);
+ updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_ENABLE,
+ enable != null ? enable.getValue() : null, userId, true);
+ Setting include = getGlobalSetting(
+ Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB);
+ updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB,
+ include != null ? include.getValue() : null, userId, true);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ if (newRestrictions.containsKey(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)
+ != prevRestrictions.containsKey(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ Setting setting = getGlobalSetting(
+ Settings.Global.PREFERRED_NETWORK_MODE);
+ updateGlobalSetting(Settings.Global.PREFERRED_NETWORK_MODE,
+ setting != null ? setting.getValue() : null, userId, true);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ });
+ }
+
private Cursor getAllGlobalSettings(String[] projection) {
if (DEBUG) {
Slog.v(LOG_TAG, "getAllGlobalSettings()");
@@ -590,7 +724,7 @@
synchronized (mLock) {
// Get the settings.
SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
- SettingsRegistry.SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
+ SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
List<String> names = settingsState.getSettingNamesLocked();
@@ -617,34 +751,39 @@
// Get the value.
synchronized (mLock) {
- return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
+ return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_GLOBAL,
UserHandle.USER_SYSTEM, name);
}
}
- private boolean updateGlobalSetting(String name, String value, int requestingUserId) {
+ private boolean updateGlobalSetting(String name, String value, int requestingUserId,
+ boolean forceNotify) {
if (DEBUG) {
Slog.v(LOG_TAG, "updateGlobalSetting(" + name + ", " + value + ")");
}
- return mutateGlobalSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
+ return mutateGlobalSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE,
+ forceNotify);
}
- private boolean insertGlobalSetting(String name, String value, int requestingUserId) {
+ private boolean insertGlobalSetting(String name, String value, int requestingUserId,
+ boolean forceNotify) {
if (DEBUG) {
Slog.v(LOG_TAG, "insertGlobalSetting(" + name + ", " + value + ")");
}
- return mutateGlobalSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
+ return mutateGlobalSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT,
+ forceNotify);
}
- private boolean deleteGlobalSetting(String name, int requestingUserId) {
+ private boolean deleteGlobalSetting(String name, int requestingUserId, boolean forceNotify) {
if (DEBUG) {
Slog.v(LOG_TAG, "deleteGlobalSettingLocked(" + name + ")");
}
- return mutateGlobalSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
+ return mutateGlobalSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE,
+ forceNotify);
}
private boolean mutateGlobalSetting(String name, String value, int requestingUserId,
- int operation) {
+ int operation, boolean forceNotify) {
// Make sure the caller can change the settings - treated as secure.
enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
@@ -662,20 +801,19 @@
switch (operation) {
case MUTATION_OPERATION_INSERT: {
return mSettingsRegistry
- .insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
- UserHandle.USER_SYSTEM, name, value, getCallingPackage());
+ .insertSettingLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM,
+ name, value, getCallingPackage(), forceNotify);
}
case MUTATION_OPERATION_DELETE: {
- return mSettingsRegistry.deleteSettingLocked(
- SettingsRegistry.SETTINGS_TYPE_GLOBAL,
- UserHandle.USER_SYSTEM, name);
+ return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_GLOBAL,
+ UserHandle.USER_SYSTEM, name, forceNotify);
}
case MUTATION_OPERATION_UPDATE: {
return mSettingsRegistry
- .updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
- UserHandle.USER_SYSTEM, name, value, getCallingPackage());
+ .updateSettingLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM,
+ name, value, getCallingPackage(), forceNotify);
}
}
}
@@ -693,7 +831,7 @@
synchronized (mLock) {
List<String> names = mSettingsRegistry.getSettingsNamesLocked(
- SettingsRegistry.SETTINGS_TYPE_SECURE, callingUserId);
+ SETTINGS_TYPE_SECURE, callingUserId);
final int nameCount = names.size();
@@ -712,7 +850,7 @@
}
Setting setting = mSettingsRegistry.getSettingLocked(
- SettingsRegistry.SETTINGS_TYPE_SECURE, owningUserId, name);
+ SETTINGS_TYPE_SECURE, owningUserId, name);
appendSettingToCursor(result, setting);
}
@@ -738,39 +876,44 @@
// Get the value.
synchronized (mLock) {
- return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
+ return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SECURE,
owningUserId, name);
}
}
- private boolean insertSecureSetting(String name, String value, int requestingUserId) {
+ private boolean insertSecureSetting(String name, String value, int requestingUserId,
+ boolean forceNotify) {
if (DEBUG) {
Slog.v(LOG_TAG, "insertSecureSetting(" + name + ", " + value + ", "
+ requestingUserId + ")");
}
- return mutateSecureSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
+ return mutateSecureSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT,
+ forceNotify);
}
- private boolean deleteSecureSetting(String name, int requestingUserId) {
+ private boolean deleteSecureSetting(String name, int requestingUserId, boolean forceNotify) {
if (DEBUG) {
Slog.v(LOG_TAG, "deleteSecureSetting(" + name + ", " + requestingUserId + ")");
}
- return mutateSecureSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
+ return mutateSecureSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE,
+ forceNotify);
}
- private boolean updateSecureSetting(String name, String value, int requestingUserId) {
+ private boolean updateSecureSetting(String name, String value, int requestingUserId,
+ boolean forceNotify) {
if (DEBUG) {
Slog.v(LOG_TAG, "updateSecureSetting(" + name + ", " + value + ", "
+ requestingUserId + ")");
}
- return mutateSecureSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
+ return mutateSecureSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE,
+ forceNotify);
}
private boolean mutateSecureSetting(String name, String value, int requestingUserId,
- int operation) {
+ int operation, boolean forceNotify) {
// Make sure the caller can change the settings.
enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
@@ -793,28 +936,25 @@
// Special cases for location providers (sigh).
if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
- return updateLocationProvidersAllowedLocked(value, owningUserId);
+ return updateLocationProvidersAllowedLocked(value, owningUserId, forceNotify);
}
// Mutate the value.
synchronized (mLock) {
switch (operation) {
case MUTATION_OPERATION_INSERT: {
- return mSettingsRegistry
- .insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
- owningUserId, name, value, getCallingPackage());
+ return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE,
+ owningUserId, name, value, getCallingPackage(), forceNotify);
}
case MUTATION_OPERATION_DELETE: {
- return mSettingsRegistry.deleteSettingLocked(
- SettingsRegistry.SETTINGS_TYPE_SECURE,
- owningUserId, name);
+ return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SECURE,
+ owningUserId, name, forceNotify);
}
case MUTATION_OPERATION_UPDATE: {
- return mSettingsRegistry
- .updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
- owningUserId, name, value, getCallingPackage());
+ return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SECURE,
+ owningUserId, name, value, getCallingPackage(), forceNotify);
}
}
}
@@ -832,7 +972,7 @@
synchronized (mLock) {
List<String> names = mSettingsRegistry.getSettingsNamesLocked(
- SettingsRegistry.SETTINGS_TYPE_SYSTEM, callingUserId);
+ SETTINGS_TYPE_SYSTEM, callingUserId);
final int nameCount = names.size();
@@ -847,7 +987,7 @@
name);
Setting setting = mSettingsRegistry.getSettingLocked(
- SettingsRegistry.SETTINGS_TYPE_SYSTEM, owningUserId, name);
+ SETTINGS_TYPE_SYSTEM, owningUserId, name);
appendSettingToCursor(result, setting);
}
@@ -868,8 +1008,7 @@
// Get the value.
synchronized (mLock) {
- return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
- owningUserId, name);
+ return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SYSTEM, owningUserId, name);
}
}
@@ -944,22 +1083,19 @@
switch (operation) {
case MUTATION_OPERATION_INSERT: {
validateSystemSettingValue(name, value);
- return mSettingsRegistry
- .insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
- owningUserId, name, value, getCallingPackage());
+ return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SYSTEM,
+ owningUserId, name, value, getCallingPackage(), false);
}
case MUTATION_OPERATION_DELETE: {
- return mSettingsRegistry.deleteSettingLocked(
- SettingsRegistry.SETTINGS_TYPE_SYSTEM,
- owningUserId, name);
+ return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SYSTEM,
+ owningUserId, name, false);
}
case MUTATION_OPERATION_UPDATE: {
validateSystemSettingValue(name, value);
- return mSettingsRegistry
- .updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
- owningUserId, name, value, getCallingPackage());
+ return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SYSTEM,
+ owningUserId, name, value, getCallingPackage(), false);
}
}
@@ -1003,8 +1139,8 @@
* Checks whether changing a setting to a value is prohibited by the corresponding user
* restriction.
*
- * <p>See also {@link com.android.server.pm.UserRestrictionsUtils#applyUserRestrictionLR},
- * which should be in sync with this method.
+ * <p>See also {@link com.android.server.pm.UserRestrictionsUtils#applyUserRestriction(
+ * Context, int, String, boolean)}, which should be in sync with this method.
*
* @return true if the change is prohibited, false if the change is allowed.
*/
@@ -1177,13 +1313,19 @@
*
* @returns whether the enabled location providers changed.
*/
- private boolean updateLocationProvidersAllowedLocked(String value, int owningUserId) {
+ private boolean updateLocationProvidersAllowedLocked(String value, int owningUserId,
+ boolean forceNotify) {
if (TextUtils.isEmpty(value)) {
return false;
}
final char prefix = value.charAt(0);
if (prefix != '+' && prefix != '-') {
+ if (forceNotify) {
+ final int key = makeKey(SETTINGS_TYPE_SECURE, owningUserId);
+ mSettingsRegistry.notifyForSettingsChange(key,
+ Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
+ }
return false;
}
@@ -1232,12 +1374,17 @@
}
} else {
// nothing changed, so no need to update the database
+ if (forceNotify) {
+ final int key = makeKey(SETTINGS_TYPE_SECURE, owningUserId);
+ mSettingsRegistry.notifyForSettingsChange(key,
+ Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
+ }
return false;
}
- return mSettingsRegistry.insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
+ return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE,
owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders,
- getCallingPackage());
+ getCallingPackage(), forceNotify);
}
private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
@@ -1270,11 +1417,19 @@
"get/set setting for user", null);
}
- private static Bundle packageValueForCallResult(Setting setting) {
- if (setting == null) {
- return NULL_SETTING;
+ private Bundle packageValueForCallResult(Setting setting,
+ boolean trackingGeneration) {
+ if (!trackingGeneration) {
+ if (setting.isNull()) {
+ return NULL_SETTING_BUNDLE;
+ }
+ return Bundle.forPair(Settings.NameValueTable.VALUE, setting.getValue());
}
- return Bundle.forPair(Settings.NameValueTable.VALUE, setting.getValue());
+ Bundle result = new Bundle();
+ result.putString(Settings.NameValueTable.VALUE,
+ !setting.isNull() ? setting.getValue() : null);
+ mSettingsRegistry.mGenerationRegistry.addGenerationData(result, setting.getkey());
+ return result;
}
private static int getRequestingUserId(Bundle args) {
@@ -1283,6 +1438,10 @@
: callingUserId;
}
+ private boolean isTrackingGeneration(Bundle args) {
+ return args != null && args.containsKey(Settings.CALL_METHOD_TRACK_GENERATION_KEY);
+ }
+
private static String getSettingValue(Bundle args) {
return (args != null) ? args.getString(Settings.NameValueTable.VALUE) : null;
}
@@ -1299,7 +1458,7 @@
}
private static MatrixCursor packageSettingForQuery(Setting setting, String[] projection) {
- if (setting == null) {
+ if (setting.isNull()) {
return new MatrixCursor(projection, 0);
}
MatrixCursor cursor = new MatrixCursor(projection, 1);
@@ -1324,7 +1483,7 @@
}
private static void appendSettingToCursor(MatrixCursor cursor, Setting setting) {
- if (setting == null) {
+ if (setting.isNull()) {
return;
}
final int columnCount = cursor.getColumnCount();
@@ -1448,26 +1607,22 @@
final class SettingsRegistry {
private static final String DROPBOX_TAG_USERLOG = "restricted_profile_ssaid";
- private static final int SETTINGS_TYPE_GLOBAL = 0;
- private static final int SETTINGS_TYPE_SYSTEM = 1;
- private static final int SETTINGS_TYPE_SECURE = 2;
-
- private static final int SETTINGS_TYPE_MASK = 0xF0000000;
- private static final int SETTINGS_TYPE_SHIFT = 28;
-
private static final String SETTINGS_FILE_GLOBAL = "settings_global.xml";
private static final String SETTINGS_FILE_SYSTEM = "settings_system.xml";
private static final String SETTINGS_FILE_SECURE = "settings_secure.xml";
private final SparseArray<SettingsState> mSettingsStates = new SparseArray<>();
- private final BackupManager mBackupManager;
+ private GenerationRegistry mGenerationRegistry;
private final Handler mHandler;
+ private final BackupManager mBackupManager;
+
public SettingsRegistry() {
- mBackupManager = new BackupManager(getContext());
mHandler = new MyHandler(getContext().getMainLooper());
+ mGenerationRegistry = new GenerationRegistry(mLock);
+ mBackupManager = new BackupManager(getContext());
migrateAllLegacySettingsIfNeeded();
}
@@ -1554,28 +1709,31 @@
});
}
}
+
+ // Nuke generation tracking data
+ mGenerationRegistry.onUserRemoved(userId);
}
public boolean insertSettingLocked(int type, int userId, String name, String value,
- String packageName) {
+ String packageName, boolean forceNotify) {
final int key = makeKey(type, userId);
SettingsState settingsState = peekSettingsStateLocked(key);
final boolean success = settingsState.insertSettingLocked(name, value, packageName);
- if (success) {
+ if (forceNotify || success) {
notifyForSettingsChange(key, name);
}
return success;
}
- public boolean deleteSettingLocked(int type, int userId, String name) {
+ public boolean deleteSettingLocked(int type, int userId, String name, boolean forceNotify) {
final int key = makeKey(type, userId);
SettingsState settingsState = peekSettingsStateLocked(key);
final boolean success = settingsState.deleteSettingLocked(name);
- if (success) {
+ if (forceNotify || success) {
notifyForSettingsChange(key, name);
}
return success;
@@ -1589,13 +1747,13 @@
}
public boolean updateSettingLocked(int type, int userId, String name, String value,
- String packageName) {
+ String packageName, boolean forceNotify) {
final int key = makeKey(type, userId);
SettingsState settingsState = peekSettingsStateLocked(key);
final boolean success = settingsState.updateSettingLocked(name, value, packageName);
- if (success) {
+ if (forceNotify || success) {
notifyForSettingsChange(key, name);
}
@@ -1786,38 +1944,6 @@
}
private void notifyForSettingsChange(int key, String name) {
- // Update the system property *first*, so if someone is listening for
- // a notification and then using the contract class to get their data,
- // the system property will be updated and they'll get the new data.
-
- boolean backedUpDataChanged = false;
- String property = null;
- if (isGlobalSettingsKey(key)) {
- property = Settings.Global.SYS_PROP_SETTING_VERSION;
- backedUpDataChanged = true;
- } else if (isSecureSettingsKey(key)) {
- property = Settings.Secure.SYS_PROP_SETTING_VERSION;
- backedUpDataChanged = true;
- } else if (isSystemSettingsKey(key)) {
- property = Settings.System.SYS_PROP_SETTING_VERSION;
- backedUpDataChanged = true;
- }
-
- if (property != null) {
- final long version = SystemProperties.getLong(property, 0) + 1;
- SystemProperties.set(property, Long.toString(version));
- if (DEBUG) {
- Slog.v(LOG_TAG, "System property " + property + "=" + version);
- }
- }
-
- // Inform the backup manager about a data change
- if (backedUpDataChanged) {
- mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
- }
-
- // Now send the notification through the content framework.
-
final int userId = getUserIdFromKey(key);
Uri uri = getNotificationUriFor(key, name);
@@ -1825,13 +1951,19 @@
userId, 0, uri).sendToTarget();
if (isSecureSettingsKey(key)) {
- maybeNotifyProfiles(userId, uri, name, sSecureCloneToManagedSettings);
+ maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name,
+ sSecureCloneToManagedSettings);
} else if (isSystemSettingsKey(key)) {
- maybeNotifyProfiles(userId, uri, name, sSystemCloneToManagedSettings);
+ maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name,
+ sSystemCloneToManagedSettings);
}
+
+ mGenerationRegistry.incrementGeneration(key);
+
+ mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
}
- private void maybeNotifyProfiles(int userId, Uri uri, String name,
+ private void maybeNotifyProfiles(int type, int userId, Uri uri, String name,
Set<String> keysCloned) {
if (keysCloned.contains(name)) {
for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) {
@@ -1839,23 +1971,15 @@
if (profileId != userId) {
mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
profileId, 0, uri).sendToTarget();
+ final int key = makeKey(type, profileId);
+ mGenerationRegistry.incrementGeneration(key);
+
+ mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
}
}
}
}
- private int makeKey(int type, int userId) {
- return (type << SETTINGS_TYPE_SHIFT) | userId;
- }
-
- private int getTypeFromKey(int key) {
- return key >> SETTINGS_TYPE_SHIFT;
- }
-
- private int getUserIdFromKey(int key) {
- return key & ~SETTINGS_TYPE_MASK;
- }
-
private boolean isGlobalSettingsKey(int key) {
return getTypeFromKey(key) == SETTINGS_TYPE_GLOBAL;
}
@@ -1953,7 +2077,7 @@
public void upgradeIfNeededLocked() {
// The version of all settings for a user is the same (all users have secure).
SettingsState secureSettings = getSettingsLocked(
- SettingsRegistry.SETTINGS_TYPE_SECURE, mUserId);
+ SETTINGS_TYPE_SECURE, mUserId);
// Try an update from the current state.
final int oldVersion = secureSettings.getVersionLocked();
@@ -1987,7 +2111,7 @@
// Set the global settings version if owner.
if (mUserId == UserHandle.USER_SYSTEM) {
SettingsState globalSettings = getSettingsLocked(
- SettingsRegistry.SETTINGS_TYPE_GLOBAL, mUserId);
+ SETTINGS_TYPE_GLOBAL, mUserId);
globalSettings.setVersionLocked(newVersion);
}
@@ -1996,7 +2120,7 @@
// Set the system settings version.
SettingsState systemSettings = getSettingsLocked(
- SettingsRegistry.SETTINGS_TYPE_SYSTEM, mUserId);
+ SETTINGS_TYPE_SYSTEM, mUserId);
systemSettings.setVersionLocked(newVersion);
}
@@ -2086,7 +2210,7 @@
Setting currentSetting = secureSettings.getSettingLocked(
Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);
if (defaultComponent != null && !defaultComponent.isEmpty() &&
- currentSetting == null) {
+ currentSetting.isNull()) {
secureSettings.insertSettingLocked(
Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
defaultComponent,
@@ -2102,7 +2226,7 @@
final SettingsState globalSettings = getGlobalSettingsLocked();
Setting currentSetting = globalSettings.getSettingLocked(
Settings.Global.ADD_USERS_WHEN_LOCKED);
- if (currentSetting == null) {
+ if (currentSetting.isNull()) {
globalSettings.insertSettingLocked(
Settings.Global.ADD_USERS_WHEN_LOCKED,
getContext().getResources().getBoolean(
@@ -2128,7 +2252,7 @@
final SettingsState secureSettings = getSecureSettingsLocked(userId);
Setting currentSetting = secureSettings.getSettingLocked(
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
- if (currentSetting == null) {
+ if (currentSetting.isNull()) {
secureSettings.insertSettingLocked(
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
getContext().getResources().getBoolean(
@@ -2144,7 +2268,7 @@
Setting currentSetting = secureSettings.getSettingLocked(
Settings.Secure.ENABLED_VR_LISTENERS);
- if (currentSetting == null) {
+ if (currentSetting.isNull()) {
ArraySet<ComponentName> l =
SystemConfig.getInstance().getDefaultVrComponents();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index dde9709..6dfd0e6 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -16,6 +16,7 @@
package com.android.providers.settings;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
@@ -109,6 +110,14 @@
@GuardedBy("mLock")
private final File mStatePersistFile;
+ private final Setting mNullSetting = new Setting(null, null, null) {
+ @Override
+ public boolean isNull() {
+ return true;
+ }
+ };
+
+ @GuardedBy("mLock")
public final int mKey;
@GuardedBy("mLock")
@@ -198,9 +207,13 @@
// The settings provider must hold its lock when calling here.
public Setting getSettingLocked(String name) {
if (TextUtils.isEmpty(name)) {
- return null;
+ return mNullSetting;
}
- return mSettings.get(name);
+ Setting setting = mSettings.get(name);
+ if (setting != null) {
+ return new Setting(setting);
+ }
+ return mNullSetting;
}
// The settings provider must hold its lock when calling here.
@@ -549,12 +562,19 @@
}
}
- public final class Setting {
+ class Setting {
private String name;
private String value;
private String packageName;
private String id;
+ public Setting(Setting other) {
+ name = other.name;
+ value = other.value;
+ packageName = other.packageName;
+ id = other.id;
+ }
+
public Setting(String name, String value, String packageName) {
init(name, value, packageName, String.valueOf(mNextId++));
}
@@ -575,6 +595,10 @@
return name;
}
+ public int getkey() {
+ return mKey;
+ }
+
public String getValue() {
return value;
}
@@ -587,6 +611,10 @@
return id;
}
+ public boolean isNull() {
+ return false;
+ }
+
public boolean update(String value, String packageName) {
if (Objects.equal(value, this.value)) {
return false;
diff --git a/packages/Shell/src/com/android/shell/BugreportWarningActivity.java b/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
index da33a65..2426ba0 100644
--- a/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
+++ b/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
@@ -25,6 +25,7 @@
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
+import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.widget.CheckBox;
@@ -59,7 +60,15 @@
ap.mNegativeButtonListener = this;
mConfirmRepeat = (CheckBox) ap.mView.findViewById(android.R.id.checkbox);
- mConfirmRepeat.setChecked(getWarningState(this, STATE_UNKNOWN) != STATE_SHOW);
+
+ final int state = getWarningState(this, STATE_UNKNOWN);
+ final boolean checked;
+ if (Build.TYPE.equals("user")) {
+ checked = state == STATE_HIDE; // Only checks if specifically set to.
+ } else {
+ checked = state != STATE_SHOW; // Checks by default.
+ }
+ mConfirmRepeat.setChecked(checked);
setupAlert();
}
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 07c1546..44e956a 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -63,6 +63,7 @@
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.SystemProperties;
import android.service.notification.StatusBarNotification;
@@ -517,7 +518,14 @@
mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm_dont_repeat));
final boolean firstTime = propertyState == null || propertyState == STATE_UNKNOWN;
if (firstTime) {
- assertTrue("Checkbox should be checked by default", dontShowAgain.isChecked());
+ if (Build.TYPE.equals("user")) {
+ assertFalse("Checkbox should NOT be checked by default on user builds",
+ dontShowAgain.isChecked());
+ mUiBot.click(dontShowAgain, "dont-show-again");
+ } else {
+ assertTrue("Checkbox should be checked by default on build type " + Build.TYPE,
+ dontShowAgain.isChecked());
+ }
} else {
assertFalse("Checkbox should not be checked", dontShowAgain.isChecked());
mUiBot.click(dontShowAgain, "dont-show-again");
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index f60a3b6..4d72cc8 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -69,7 +69,7 @@
<RadioButton
android:id="@+id/silent_importance"
android:layout_width="wrap_content"
- android:layout_height="48dp"
+ android:layout_height="40dp"
android:paddingStart="32dp"
android:text="@string/show_silently"
style="@style/TextAppearance.NotificationGuts.Radio"
@@ -77,7 +77,7 @@
<RadioButton
android:id="@+id/block_importance"
android:layout_width="wrap_content"
- android:layout_height="48dp"
+ android:layout_height="40dp"
android:paddingStart="32dp"
android:text="@string/block"
style="@style/TextAppearance.NotificationGuts.Radio"
@@ -85,7 +85,7 @@
<RadioButton
android:id="@+id/reset_importance"
android:layout_width="wrap_content"
- android:layout_height="48dp"
+ android:layout_height="40dp"
android:paddingStart="32dp"
style="@style/TextAppearance.NotificationGuts.Radio"
android:buttonTint="@color/notification_guts_buttons" />
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index caa1585..beba4f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1123,6 +1123,9 @@
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
updateMaxHeights();
+ if (mSettingsIconRow != null) {
+ mSettingsIconRow.updateVerticalLocation();
+ }
}
private void updateMaxHeights() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 057b020..4650a1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -299,12 +299,13 @@
private void applyAuto() {
mSeekBar.setEnabled(!mAuto);
- final ColorStateList tint = mAuto ? mInactiveSliderTint : mActiveSliderTint;
+ final ColorStateList sliderTint = mAuto ? mInactiveSliderTint : mActiveSliderTint;
+ final ColorStateList starTint = mAuto ? mActiveSliderTint : mInactiveSliderTint;
Drawable icon = mAutoButton.getDrawable().mutate();
- icon.setTintList(tint);
+ icon.setTintList(starTint);
mAutoButton.setImageDrawable(icon);
- mSeekBar.setProgressTintList(tint);
- mSeekBar.setThumbTintList(tint);
+ mSeekBar.setProgressTintList(sliderTint);
+ mSeekBar.setThumbTintList(sliderTint);
if (mAuto) {
mSeekBar.setProgress(mNotificationImportance);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
index 060d8f4..4a1c451 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
@@ -244,7 +244,6 @@
}
public void setIconLocation(boolean onLeft) {
- updateVerticalLocation();
if ((mIconPlaced && onLeft == mOnLeft) || mSnapping || mParent == null
|| mGearIcon.getWidth() == 0) {
// Do nothing
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index a7f4314..a41a8ef 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -721,6 +721,9 @@
}
immersive = (aInfo.flags & ActivityInfo.FLAG_IMMERSIVE) != 0;
+
+ requestedVrComponent = (aInfo.requestedVrComponent == null) ?
+ null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
} else {
realActivity = null;
taskAffinity = null;
@@ -732,6 +735,7 @@
noDisplay = false;
mActivityType = APPLICATION_ACTIVITY_TYPE;
immersive = false;
+ requestedVrComponent = null;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index a7c994b3..37bd401 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3457,7 +3457,8 @@
// First things first: if this activity is currently visible,
// and the resumed activity is not yet visible, then hold off on
// finishing until the resumed one becomes visible.
- if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)) {
+ if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)
+ && !mStackSupervisor.allResumedActivitiesVisible()) {
if (!mStackSupervisor.mStoppingActivities.contains(r)) {
addToStopping(r, false /* immediate */);
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index f281683..66bc51c 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1097,7 +1097,21 @@
// Don't debug things in the system process
if (!aInfo.processName.equals("system")) {
if ((startFlags & ActivityManager.START_FLAG_DEBUG) != 0) {
- mService.setDebugApp(aInfo.processName, true, false);
+ final ProcessRecord app = mService.getProcessRecordLocked(
+ aInfo.processName, aInfo.applicationInfo.uid, true);
+ // If the process already started, we can't wait for debugger and shouldn't
+ // modify the debug settings.
+ // For non-persistent debug, normally we set the debug app here, and restores
+ // to the original at attachApplication time. However, if the app process
+ // already exists, we won't get another attachApplication, and the debug setting
+ // never gets restored. Furthermore, if we get two such calls back-to-back,
+ // both mOrigDebugApp and mDebugApp will become the same app, and it won't be
+ // cleared even if we get attachApplication after the app process is killed.
+ if (app == null || app.thread == null) {
+ mService.setDebugApp(aInfo.processName, true, false);
+ } else {
+ Slog.w(TAG, "Ignoring waitForDebugger because process already exists");
+ }
}
if ((startFlags & ActivityManager.START_FLAG_NATIVE_DEBUGGING) != 0) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index a6dfab0..0874fa7 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3940,33 +3940,40 @@
}
}
+ private int getAbsoluteVolumeIndex(int index) {
+ /* Special handling for Bluetooth Absolute Volume scenario
+ * If we send full audio gain, some accessories are too loud even at its lowest
+ * volume. We are not able to enumerate all such accessories, so here is the
+ * workaround from phone side.
+ * Pre-scale volume at lowest volume steps 1 2 and 3.
+ * For volume step 0, set audio gain to 0 as some accessories won't mute on their end.
+ */
+ if (index == 0) {
+ // 0% for volume 0
+ index = 0;
+ } else if (index == 1) {
+ // 50% for volume 1
+ index = (int)(mIndexMax * 0.5) /10;
+ } else if (index == 2) {
+ // 70% for volume 2
+ index = (int)(mIndexMax * 0.70) /10;
+ } else if (index == 3) {
+ // 85% for volume 3
+ index = (int)(mIndexMax * 0.85) /10;
+ } else {
+ // otherwise, full gain
+ index = (mIndexMax + 5)/10;
+ }
+ return index;
+ }
+
// must be called while synchronized VolumeStreamState.class
public void applyDeviceVolume_syncVSS(int device) {
int index;
if (mIsMuted) {
index = 0;
} else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported) {
- /* Special handling for Bluetooth Absolute Volume scenario
- * If we send full audio gain, some accessories are too loud even at its lowest
- * volume. We are not able to enumerate all such accessories, so here is the
- * workaround from phone side.
- * For the lowest volume steps 1 and 2, restrict audio gain to 50% and 75%.
- * For volume step 0, set audio gain to 0 as some accessories won't mute on their end.
- */
- int i = (getIndex(device) + 5)/10;
- if (i == 0) {
- // 0% for volume 0
- index = 0;
- } else if (i == 1) {
- // 50% for volume 1
- index = (int)(mIndexMax * 0.5) /10;
- } else if (i == 2) {
- // 75% for volume 2
- index = (int)(mIndexMax * 0.75) /10;
- } else {
- // otherwise, full gain
- index = (mIndexMax + 5)/10;
- }
+ index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
} else if ((device & mFullVolumeDevices) != 0) {
index = (mIndexMax + 5)/10;
} else {
@@ -3984,9 +3991,10 @@
if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
if (mIsMuted) {
index = 0;
- } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
- mAvrcpAbsVolSupported)
- || ((device & mFullVolumeDevices) != 0)) {
+ } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
+ mAvrcpAbsVolSupported) {
+ index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
+ } else if ((device & mFullVolumeDevices) != 0) {
index = (mIndexMax + 5)/10;
} else {
index = (mIndexMap.valueAt(i) + 5)/10;
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 92aa8d9..fcf2162 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1301,7 +1301,7 @@
}
getJobScheduler().scheduleAsPackage(b.build(), syncOperation.owningPackage,
- syncOperation.target.userId, "sync");
+ syncOperation.target.userId, syncOperation.wakeLockName());
}
/**
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 9ab4386..590d075 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -150,19 +150,9 @@
this.sourceTag = tag;
}
- if (this.sourceTag != null) {
- StringBuilder sb = new StringBuilder();
- sb.append(job.getService().getPackageName());
- sb.append('/');
- sb.append(this.sourceTag);
- if (sourcePackageName != null) {
- sb.append('/');
- sb.append(this.sourcePackageName);
- }
- this.batteryName = sb.toString();
- } else {
- this.batteryName = job.getService().flattenToShortString();
- }
+ this.batteryName = this.sourceTag != null
+ ? this.sourceTag + ":" + job.getService().getPackageName()
+ : job.getService().flattenToShortString();
this.tag = "*job*/" + this.batteryName;
this.earliestRunTimeElapsedMillis = earliestRunTimeElapsedMillis;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e411579..9bdb149 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3316,9 +3316,9 @@
mNotificationList.remove(index);
- cancelNotificationLocked(r, sendDelete, reason);
cancelGroupChildrenLocked(r, callingUid, callingPid, listenerName,
REASON_GROUP_SUMMARY_CANCELED);
+ cancelNotificationLocked(r, sendDelete, reason);
updateLightsLocked();
}
}
diff --git a/services/core/java/com/android/server/os/SchedulingPolicyService.java b/services/core/java/com/android/server/os/SchedulingPolicyService.java
index 80faf473..f98012b 100644
--- a/services/core/java/com/android/server/os/SchedulingPolicyService.java
+++ b/services/core/java/com/android/server/os/SchedulingPolicyService.java
@@ -66,7 +66,7 @@
final int callingUid = Binder.getCallingUid();
switch (callingUid) {
case Process.AUDIOSERVER_UID: // fastcapture, fastmixer
- case Process.MEDIA_UID: // camera
+ case Process.CAMERASERVER_UID: // camera high frame rate recording
return true;
default:
return false;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 38144e4..a328f00 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2050,17 +2050,18 @@
final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
| PackageManager.FLAG_PERMISSION_POLICY_FIXED;
- synchronized (mPackages) {
- for (String permission : pkg.requestedPermissions) {
- BasePermission bp = mSettings.mPermissions.get(permission);
- if (bp != null && (bp.isRuntime() || bp.isDevelopment())
- && (grantedPermissions == null
- || ArrayUtils.contains(grantedPermissions, permission))) {
- final int flags = permissionsState.getPermissionFlags(permission, userId);
- // Installer cannot change immutable permissions.
- if ((flags & immutableFlags) == 0) {
- grantRuntimePermission(pkg.packageName, permission, userId);
- }
+ for (String permission : pkg.requestedPermissions) {
+ final BasePermission bp;
+ synchronized (mPackages) {
+ bp = mSettings.mPermissions.get(permission);
+ }
+ if (bp != null && (bp.isRuntime() || bp.isDevelopment())
+ && (grantedPermissions == null
+ || ArrayUtils.contains(grantedPermissions, permission))) {
+ final int flags = permissionsState.getPermissionFlags(permission, userId);
+ // Installer cannot change immutable permissions.
+ if ((flags & immutableFlags) == 0) {
+ grantRuntimePermission(pkg.packageName, permission, userId);
}
}
}
@@ -13794,10 +13795,26 @@
final PackageParser.Package oldPackage;
final String pkgName = pkg.packageName;
final int[] allUsers;
+ final int[] installedUsers;
- // First find the old package info and check signatures
synchronized(mPackages) {
oldPackage = mPackages.get(pkgName);
+ if (DEBUG_INSTALL) Slog.d(TAG, "replacePackageLI: new=" + pkg + ", old=" + oldPackage);
+
+ // don't allow upgrade to target a release SDK from a pre-release SDK
+ final boolean oldTargetsPreRelease = oldPackage.applicationInfo.targetSdkVersion
+ == android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
+ final boolean newTargetsPreRelease = pkg.applicationInfo.targetSdkVersion
+ == android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
+ if (oldTargetsPreRelease
+ && !newTargetsPreRelease
+ && ((policyFlags & PackageParser.PARSE_FORCE_SDK) == 0)) {
+ Slog.w(TAG, "Can't install package targeting released sdk");
+ res.setReturnCode(PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE);
+ return;
+ }
+
+ // don't allow an upgrade from full to ephemeral
final boolean oldIsEphemeral = oldPackage.applicationInfo.isEphemeralApp();
if (isEphemeral && !oldIsEphemeral) {
// can't downgrade from full to ephemeral
@@ -13805,7 +13822,8 @@
res.setReturnCode(PackageManager.INSTALL_FAILED_EPHEMERAL_INVALID);
return;
}
- if (DEBUG_INSTALL) Slog.d(TAG, "replacePackageLI: new=" + pkg + ", old=" + oldPackage);
+
+ // verify signatures are valid
final PackageSetting ps = mSettings.mPackages.get(pkgName);
if (shouldCheckUpgradeKeySetLP(ps, scanFlags)) {
if (!checkUpgradeKeySetLP(ps, pkg)) {
@@ -13836,6 +13854,7 @@
// In case of rollback, remember per-user/profile install state
allUsers = sUserManager.getUserIds();
+ installedUsers = ps.queryInstalledUsers(allUsers, true);
}
// Update what is removed
@@ -13843,6 +13862,7 @@
res.removedInfo.uid = oldPackage.applicationInfo.uid;
res.removedInfo.removedPackage = oldPackage.packageName;
res.removedInfo.isUpdate = true;
+ res.removedInfo.origUsers = installedUsers;
final int childCount = (oldPackage.childPackages != null)
? oldPackage.childPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
@@ -14411,6 +14431,7 @@
final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0)
|| (args.volumeUuid != null));
final boolean ephemeral = ((installFlags & PackageManager.INSTALL_EPHEMERAL) != 0);
+ final boolean forceSdk = ((installFlags & PackageManager.INSTALL_FORCE_SDK) != 0);
boolean replace = false;
int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
if (args.move != null) {
@@ -14439,7 +14460,8 @@
| PackageParser.PARSE_ENFORCE_CODE
| (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
| (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0)
- | (ephemeral ? PackageParser.PARSE_IS_EPHEMERAL : 0);
+ | (ephemeral ? PackageParser.PARSE_IS_EPHEMERAL : 0)
+ | (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0);
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setDisplayMetrics(mMetrics);
@@ -19397,12 +19419,13 @@
public int movePackage(final String packageName, final String volumeUuid) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
+ final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
final int moveId = mNextMoveId.getAndIncrement();
mHandler.post(new Runnable() {
@Override
public void run() {
try {
- movePackageInternal(packageName, volumeUuid, moveId);
+ movePackageInternal(packageName, volumeUuid, moveId, user);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to move " + packageName, e);
mMoveCallbacks.notifyStatusChanged(moveId,
@@ -19414,8 +19437,7 @@
}
private void movePackageInternal(final String packageName, final String volumeUuid,
- final int moveId) throws PackageManagerException {
- final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
+ final int moveId, UserHandle user) throws PackageManagerException {
final StorageManager storage = mContext.getSystemService(StorageManager.class);
final PackageManager pm = mContext.getPackageManager();
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 8527fd4..68a19c3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1000,6 +1000,9 @@
case "-g":
sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
break;
+ case "--dont-kill":
+ sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
+ break;
case "--originating-uri":
sessionParams.originatingUri = Uri.parse(getNextArg());
break;
@@ -1035,6 +1038,9 @@
sessionParams.volumeUuid = null;
}
break;
+ case "--force-sdk":
+ sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK;
+ break;
default:
throw new IllegalArgumentException("Unknown option " + opt);
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 7debf9b..f20a36e 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -718,6 +718,21 @@
// let's log a message about it.
Slog.i(PackageManagerService.TAG, "Package " + name + " codePath changed from "
+ p.codePath + " to " + codePath + "; Retaining data and using new");
+
+ // The owner user's installed flag is set false
+ // when the application was installed by other user
+ // and the installed flag is not updated
+ // when the application is appended as system app later.
+ if ((pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0 &&
+ getDisabledSystemPkgLPr(name) == null) {
+ List<UserInfo> allUserInfos = getAllUsers();
+ if (allUserInfos != null) {
+ for (UserInfo userInfo : allUserInfos) {
+ p.setInstalled(true, userInfo.id);
+ }
+ }
+ }
+
/*
* Since we've changed paths, we need to prefer the new
* native library path over the one stored in the
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 364e9fa6..38a3f42 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -370,19 +370,6 @@
android.provider.Settings.Secure.LOCATION_MODE_OFF,
userId);
}
- // Send out notifications as some clients may want to reread the
- // value which actually changed due to a restriction having been
- // applied.
- final String property =
- android.provider.Settings.Secure.SYS_PROP_SETTING_VERSION;
- long version = SystemProperties.getLong(property, 0) + 1;
- SystemProperties.set(property, Long.toString(version));
-
- final String name = android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
- final Uri url = Uri.withAppendedPath(
- android.provider.Settings.Secure.CONTENT_URI, name);
- context.getContentResolver().notifyChange(url, null, true, userId);
-
break;
case UserManager.DISALLOW_DEBUGGING_FEATURES:
if (newValue) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 9f54b53..3b1f34a 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -515,6 +515,13 @@
}
}
+ void requestUpdateWallpaperIfNeeded() {
+ for (int i = allAppWindows.size() - 1; i >= 0; i--) {
+ final WindowState w = allAppWindows.get(i);
+ w.requestUpdateWallpaperIfNeeded();
+ }
+ }
+
boolean isRelaunching() {
return mPendingRelaunchCount > 0;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 1f16481..037eb5a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -364,8 +364,8 @@
final ArrayList<Task> tasks = stack.getTasks();
for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
final Task task = tasks.get(taskNdx);
- final WindowState win = task.getTopVisibleAppMainWindow();
- if (win == null) {
+ AppWindowToken token = task.getTopVisibleAppToken();
+ if (token == null || !token.isVisible()) {
continue;
}
@@ -375,20 +375,18 @@
* We also remove the outside touch area for resizing for all freeform
* tasks (including the focused).
*
- * (For freeform focused task, the below logic will first remove the enlarged
- * area, then add back the inner area.)
+ * We save the focused task region once we find it, and add it back at the end.
*/
+
+ if (task == focusedTask) {
+ addBackFocusedTask = true;
+ mTmpRect2.set(mTmpRect);
+ }
+
final boolean isFreeformed = task.inFreeformWorkspace();
if (task != focusedTask || isFreeformed) {
task.getDimBounds(mTmpRect);
if (isFreeformed) {
- // If we're removing a freeform, focused app from the exclusion region,
- // we need to add back its touchable frame later. Remember the touchable
- // frame now.
- if (task == focusedTask) {
- addBackFocusedTask = true;
- mTmpRect2.set(mTmpRect);
- }
// If the task is freeformed, enlarge the area to account for outside
// touch area for resize.
mTmpRect.inset(-delta, -delta);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 13b4d54..80bf803 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4426,6 +4426,8 @@
wtoken.sendAppVisibilityToClients();
}
}
+ wtoken.requestUpdateWallpaperIfNeeded();
+
if (DEBUG_ADD_REMOVE) Slog.v(
TAG_WM, "No longer Stopped: " + wtoken);
wtoken.mAppStopped = false;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index ae20ae3..dd88bea 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -73,6 +73,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
@@ -90,6 +91,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
@@ -2719,6 +2721,14 @@
mAnimateReplacingWindow = false;
}
+ void requestUpdateWallpaperIfNeeded() {
+ if (mDisplayContent != null && (mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
+ mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ mDisplayContent.layoutNeeded = true;
+ mService.mWindowPlacerLocked.requestTraversal();
+ }
+ }
+
float translateToWindowX(float x) {
float winX = x - mFrame.left;
if (mEnforceSizeCompat) {
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 1b42e44..0e930ed 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -32,8 +32,6 @@
import android.net.NetworkUtils;
import android.net.metrics.DhcpClientEvent;
import android.net.metrics.DhcpErrorEvent;
-import android.os.IBinder;
-import android.os.INetworkManagementService;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -121,6 +119,13 @@
* after pre DHCP action is complete */
public static final int CMD_PRE_DHCP_ACTION_COMPLETE = PUBLIC_BASE + 7;
+ /* Command and event notification to/from IpManager requesting the setting
+ * (or clearing) of an IPv4 LinkAddress.
+ */
+ public static final int CMD_CLEAR_LINKADDRESS = PUBLIC_BASE + 8;
+ public static final int CMD_CONFIGURE_LINKADDRESS = PUBLIC_BASE + 9;
+ public static final int EVENT_LINKADDRESS_CONFIGURED = PUBLIC_BASE + 10;
+
/* Message.arg1 arguments to CMD_POST_DHCP notification */
public static final int DHCP_SUCCESS = 1;
public static final int DHCP_FAILURE = 2;
@@ -157,7 +162,6 @@
// System services / libraries we use.
private final Context mContext;
private final Random mRandom;
- private final INetworkManagementService mNMService;
// Sockets.
// - We use a packet socket to receive, because servers send us packets bound for IP addresses
@@ -192,7 +196,8 @@
private State mDhcpInitState = new DhcpInitState();
private State mDhcpSelectingState = new DhcpSelectingState();
private State mDhcpRequestingState = new DhcpRequestingState();
- private State mDhcpHaveAddressState = new DhcpHaveAddressState();
+ private State mDhcpHaveLeaseState = new DhcpHaveLeaseState();
+ private State mConfiguringInterfaceState = new ConfiguringInterfaceState();
private State mDhcpBoundState = new DhcpBoundState();
private State mDhcpRenewingState = new DhcpRenewingState();
private State mDhcpRebindingState = new DhcpRebindingState();
@@ -219,19 +224,17 @@
addState(mWaitBeforeStartState, mDhcpState);
addState(mDhcpSelectingState, mDhcpState);
addState(mDhcpRequestingState, mDhcpState);
- addState(mDhcpHaveAddressState, mDhcpState);
- addState(mDhcpBoundState, mDhcpHaveAddressState);
- addState(mWaitBeforeRenewalState, mDhcpHaveAddressState);
- addState(mDhcpRenewingState, mDhcpHaveAddressState);
- addState(mDhcpRebindingState, mDhcpHaveAddressState);
+ addState(mDhcpHaveLeaseState, mDhcpState);
+ addState(mConfiguringInterfaceState, mDhcpHaveLeaseState);
+ addState(mDhcpBoundState, mDhcpHaveLeaseState);
+ addState(mWaitBeforeRenewalState, mDhcpHaveLeaseState);
+ addState(mDhcpRenewingState, mDhcpHaveLeaseState);
+ addState(mDhcpRebindingState, mDhcpHaveLeaseState);
addState(mDhcpInitRebootState, mDhcpState);
addState(mDhcpRebootingState, mDhcpState);
setInitialState(mStoppedState);
- IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
- mNMService = INetworkManagementService.Stub.asInterface(b);
-
mRandom = new Random();
// Used to schedule packet retransmissions.
@@ -321,18 +324,6 @@
closeQuietly(mPacketSock);
}
- private boolean setIpAddress(LinkAddress address) {
- InterfaceConfiguration ifcg = new InterfaceConfiguration();
- ifcg.setLinkAddress(address);
- try {
- mNMService.setInterfaceConfig(mIfaceName, ifcg);
- } catch (RemoteException|IllegalStateException e) {
- Log.e(TAG, "Error configuring IP address " + address + ": ", e);
- return false;
- }
- return true;
- }
-
class ReceiveThread extends Thread {
private final byte[] mPacket = new byte[DhcpPacket.MAX_LENGTH];
@@ -382,7 +373,8 @@
Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
} else {
// It's safe to call getpeername here, because we only send unicast packets if we
- // have an IP address, and we connect the UDP socket in DhcpHaveAddressState#enter.
+ // have an IP address, and we connect the UDP socket before
+ // ConfiguringInterfaceState#exit.
if (DBG) Log.d(TAG, "Unicasting " + description + " to " + Os.getpeername(mUdpSock));
Os.write(mUdpSock, buf);
}
@@ -460,6 +452,7 @@
}
abstract class LoggingState extends State {
+ @Override
public void enter() {
if (STATE_DBG) Log.d(TAG, "Entering state " + getName());
DhcpClientEvent.logStateEvent(mIfaceName, getName());
@@ -759,7 +752,7 @@
mOffer = null;
Log.d(TAG, "Confirmed lease: " + mDhcpLease);
setDhcpLeaseExpiry(packet);
- transitionTo(mDhcpBoundState);
+ transitionTo(mConfiguringInterfaceState);
}
} else if (packet instanceof DhcpNakPacket) {
// TODO: Wait a while before returning into INIT state.
@@ -776,24 +769,52 @@
}
}
- class DhcpHaveAddressState extends LoggingState {
+ class DhcpHaveLeaseState extends LoggingState {
@Override
public void enter() {
super.enter();
- if (!setIpAddress(mDhcpLease.ipAddress) ||
- (mDhcpLease.serverAddress != null &&
- !connectUdpSock((mDhcpLease.serverAddress)))) {
- notifyFailure();
- // There's likely no point in going into DhcpInitState here, we'll probably just
- // repeat the transaction, get the same IP address as before, and fail.
- transitionTo(mStoppedState);
- }
}
@Override
public void exit() {
- if (DBG) Log.d(TAG, "Clearing IP address");
- setIpAddress(new LinkAddress("0.0.0.0/0"));
+ // Tell IpManager to clear the IPv4 address. There is no need to
+ // wait for confirmation since any subsequent packets are sent from
+ // INADDR_ANY anyway (DISCOVER, REQUEST).
+ mController.sendMessage(CMD_CLEAR_LINKADDRESS);
+ }
+ }
+
+ class ConfiguringInterfaceState extends LoggingState {
+ @Override
+ public void enter() {
+ super.enter();
+ mController.sendMessage(CMD_CONFIGURE_LINKADDRESS, mDhcpLease.ipAddress);
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ super.processMessage(message);
+ switch (message.what) {
+ case EVENT_LINKADDRESS_CONFIGURED:
+ if (mDhcpLease.serverAddress != null &&
+ !connectUdpSock(mDhcpLease.serverAddress)) {
+ // There's likely no point in going into DhcpInitState here, we'll probably
+ // just repeat the transaction, get the same IP address as before, and fail.
+ //
+ // NOTE: It is observed that connectUdpSock() basically never fails, due to
+ // SO_BINDTODEVICE. Examining the local socket address shows it will happily
+ // return an IPv4 address from another interface, or even return "0.0.0.0".
+ //
+ // TODO: Consider deleting this check, following testing on several kernels.
+ notifyFailure();
+ transitionTo(mStoppedState);
+ } else {
+ transitionTo(mDhcpBoundState);
+ }
+ return HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
}
}
@@ -803,8 +824,8 @@
super.enter();
mOneshotTimeoutAlarm.cancel();
notifySuccess();
- // TODO: DhcpStateMachine only supported renewing at 50% of the lease time, and did not
- // support rebinding. Once the legacy DHCP client is gone, fix this.
+ // TODO: DhcpStateMachine only supported renewing at 50% of the lease time,
+ // and did not support rebinding. Now that the legacy DHCP client is gone, fix this.
scheduleRenew();
}
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index f6a4eb8..16791ed 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -766,6 +766,19 @@
return (delta != ProvisioningChange.LOST_PROVISIONING);
}
+ private boolean setIPv4Address(LinkAddress address) {
+ final InterfaceConfiguration ifcg = new InterfaceConfiguration();
+ ifcg.setLinkAddress(address);
+ try {
+ mNwService.setInterfaceConfig(mInterfaceName, ifcg);
+ if (VDBG) Log.d(mTag, "IPv4 configuration succeeded");
+ } catch (IllegalStateException | RemoteException e) {
+ Log.e(mTag, "IPv4 configuration failed: ", e);
+ return false;
+ }
+ return true;
+ }
+
private void clearIPv4Address() {
try {
final InterfaceConfiguration ifcg = new InterfaceConfiguration();
@@ -790,7 +803,6 @@
}
private void handleIPv4Failure() {
- // TODO: Figure out to de-dup this and the same code in DhcpClient.
clearIPv4Address();
mDhcpResults = null;
final LinkProperties newLp = assembleLinkProperties();
@@ -940,7 +952,7 @@
// If we have a StaticIpConfiguration attempt to apply it and
// handle the result accordingly.
if (mConfiguration.mStaticIpConfig != null) {
- if (applyStaticIpConfig()) {
+ if (setIPv4Address(mConfiguration.mStaticIpConfig.ipAddress)) {
handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
} else {
if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }
@@ -1046,6 +1058,21 @@
}
break;
+ case DhcpClient.CMD_CLEAR_LINKADDRESS:
+ clearIPv4Address();
+ break;
+
+ case DhcpClient.CMD_CONFIGURE_LINKADDRESS: {
+ final LinkAddress ipAddress = (LinkAddress) msg.obj;
+ if (setIPv4Address(ipAddress)) {
+ mDhcpClient.sendMessage(DhcpClient.EVENT_LINKADDRESS_CONFIGURED);
+ } else {
+ Log.e(mTag, "Failed to set IPv4 address!");
+ transitionTo(mStoppingState);
+ }
+ break;
+ }
+
case DhcpClient.CMD_POST_DHCP_ACTION: {
// Note that onPostDhcpAction() is likely to be
// asynchronous, and thus there is no guarantee that we
@@ -1078,20 +1105,5 @@
}
return HANDLED;
}
-
- private boolean applyStaticIpConfig() {
- final InterfaceConfiguration ifcg = new InterfaceConfiguration();
- ifcg.setLinkAddress(mConfiguration.mStaticIpConfig.ipAddress);
- ifcg.setInterfaceUp();
- try {
- mNwService.setInterfaceConfig(mInterfaceName, ifcg);
- if (DBG) Log.d(mTag, "Static IP configuration succeeded");
- } catch (IllegalStateException | RemoteException e) {
- Log.e(mTag, "Static IP configuration failed: ", e);
- return false;
- }
-
- return true;
- }
}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index e8df24e..8f09bda 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -425,7 +425,12 @@
*/
public static final String KEY_CARRIER_METERED_APN_TYPES_STRINGS =
"carrier_metered_apn_types_strings";
-
+ /**
+ * Default APN types that are roamig-metered by the carrier
+ * @hide
+ */
+ public static final String KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS =
+ "carrier_metered_roaming_apn_types_strings";
/**
* CDMA carrier ERI (Enhanced Roaming Indicator) file name
* @hide
@@ -758,6 +763,8 @@
sDefaults.putInt(KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT, 7200);
sDefaults.putStringArray(KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{"default", "mms", "dun", "supl"});
+ sDefaults.putStringArray(KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
+ new String[]{"default", "mms", "dun", "supl"});
sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null);
sDefaults.putStringArray(KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY, null);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java
index cd15ef1..fa25b45 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java
@@ -20,33 +20,36 @@
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.os.Bundle;
-import android.util.Log;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
-import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
public class MovingSurfaceViewActivity extends Activity implements Callback {
- static final String TAG = "MovingSurfaceView";
SurfaceView mSurfaceView;
ObjectAnimator mAnimator;
class MySurfaceView extends SurfaceView {
- boolean mSlowToggled;
+ boolean mSlow;
+ boolean mScaled;
+ int mToggle = 0;
public MySurfaceView(Context context) {
super(context);
- setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mSlowToggled = !mSlowToggled;
- Log.d(TAG, "SLOW MODE: " + mSlowToggled);
- invalidate();
- }
+ setOnClickListener(v -> {
+ mToggle = (mToggle + 1) % 4;
+ mSlow = (mToggle & 0x2) != 0;
+ mScaled = (mToggle & 0x1) != 0;
+
+ mSurfaceView.setScaleX(mScaled ? 1.6f : 1f);
+ mSurfaceView.setScaleY(mScaled ? 0.8f : 1f);
+
+ setTitle("Slow=" + mSlow + ", scaled=" + mScaled);
+ invalidate();
});
setWillNotDraw(false);
}
@@ -54,7 +57,7 @@
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
- if (mSlowToggled) {
+ if (mSlow) {
try {
Thread.sleep(16);
} catch (InterruptedException e) {}
@@ -63,7 +66,7 @@
public void setMyTranslationY(float ty) {
setTranslationY(ty);
- if (mSlowToggled) {
+ if (mSlow) {
invalidate();
}
}
@@ -86,7 +89,7 @@
int size = (int) (200 * density);
content.addView(mSurfaceView, new FrameLayout.LayoutParams(
- size, size, Gravity.CENTER));
+ size, size, Gravity.CENTER_HORIZONTAL | Gravity.TOP));
mAnimator = ObjectAnimator.ofFloat(mSurfaceView, "myTranslationY",
0, size);
mAnimator.setRepeatMode(ObjectAnimator.REVERSE);
@@ -103,7 +106,7 @@
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Canvas canvas = holder.lockCanvas();
- canvas.drawARGB(0xFF, 0x00, 0xFF, 0x00);
+ canvas.drawColor(Color.WHITE);
holder.unlockCanvasAndPost(canvas);
}