Merge "docs: Fixing links to moved Fragments guide, + redirect" into nyc-dev
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index c7eca44..9461bea 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -719,7 +719,7 @@
     /**
      * Set the {@link SurfaceTexture} for this view to use. If a {@link
      * SurfaceTexture} is already being used by this view, it is immediately
-     * released and not be usable any more.  The {@link
+     * released and not usable any more.  The {@link
      * SurfaceTextureListener#onSurfaceTextureDestroyed} callback is <b>not</b>
      * called for the previous {@link SurfaceTexture}.  Similarly, the {@link
      * SurfaceTextureListener#onSurfaceTextureAvailable} callback is <b>not</b>
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 3f4b2a6..9bec6a3 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -54,6 +54,7 @@
 #include "ScopedLocalRef.h"
 #include "ScopedPrimitiveArray.h"
 #include "ScopedUtfChars.h"
+#include "fd_utils-inl.h"
 
 #include "nativebridge/native_bridge.h"
 
@@ -434,6 +435,9 @@
 }
 #endif
 
+// The list of open zygote file descriptors.
+static FileDescriptorTable* gOpenFdTable = NULL;
+
 // Utility routine to fork zygote and specialize the child process.
 static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                      jint debug_flags, jobjectArray javaRlimits,
@@ -448,6 +452,22 @@
   SetForkLoad(true);
 #endif
 
+  // Close any logging related FDs before we start evaluating the list of
+  // file descriptors.
+  __android_log_close();
+
+  // If this is the first fork for this zygote, create the open FD table.
+  // If it isn't, we just need to check whether the list of open files has
+  // changed (and it shouldn't in the normal case).
+  if (gOpenFdTable == NULL) {
+    gOpenFdTable = FileDescriptorTable::Create();
+    if (gOpenFdTable == NULL) {
+      RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table.");
+    }
+  } else if (!gOpenFdTable->Restat()) {
+    RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table.");
+  }
+
   pid_t pid = fork();
 
   if (pid == 0) {
@@ -457,6 +477,12 @@
     // Clean up any descriptors which must be closed immediately
     DetachDescriptors(env, fdsToClose);
 
+    // Re-open all remaining open file descriptors so that they aren't shared
+    // with the zygote across a fork.
+    if (!gOpenFdTable->ReopenOrDetach()) {
+      RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors.");
+    }
+
     // Keep capabilities across UID change, unless we're staying root.
     if (uid != 0) {
       EnableKeepCapabilities(env);
diff --git a/core/jni/fd_utils-inl.h b/core/jni/fd_utils-inl.h
new file mode 100644
index 0000000..db56c32
--- /dev/null
+++ b/core/jni/fd_utils-inl.h
@@ -0,0 +1,540 @@
+/*
+ * 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 <string>
+#include <unordered_map>
+#include <set>
+#include <vector>
+#include <algorithm>
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <cutils/log.h>
+#include "JNIHelp.h"
+#include "ScopedPrimitiveArray.h"
+
+// Whitelist of open paths that the zygote is allowed to keep open.
+//
+// In addition to the paths listed here, all files ending with
+// ".jar" under /system/framework" are whitelisted. See
+// FileDescriptorInfo::IsWhitelisted for the canonical definition.
+//
+// If the whitelisted path is associated with a regular file or a
+// character device, the file is reopened after a fork with the same
+// offset and mode. If the whilelisted  path is associated with a
+// AF_UNIX socket, the socket will refer to /dev/null after each
+// fork, and all operations on it will fail.
+static const char* kPathWhitelist[] = {
+  "/dev/null",
+  "/dev/socket/zygote",
+  "/dev/socket/zygote_secondary",
+  "/system/etc/event-log-tags",
+  "/sys/kernel/debug/tracing/trace_marker",
+  "/system/framework/framework-res.apk",
+  "/dev/urandom",
+  "/dev/ion",
+  "/dev/dri/renderD129", // Fixes b/31172436
+};
+
+static const char* kFdPath = "/proc/self/fd";
+
+// Keeps track of all relevant information (flags, offset etc.) of an
+// open zygote file descriptor.
+class FileDescriptorInfo {
+ public:
+  // Create a FileDescriptorInfo for a given file descriptor. Returns
+  // |NULL| if an error occurred.
+  static FileDescriptorInfo* createFromFd(int fd) {
+    struct stat f_stat;
+    // This should never happen; the zygote should always have the right set
+    // of permissions required to stat all its open files.
+    if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
+      ALOGE("Unable to stat fd %d : %s", fd, strerror(errno));
+      return NULL;
+    }
+
+    if (S_ISSOCK(f_stat.st_mode)) {
+      std::string socket_name;
+      if (!GetSocketName(fd, &socket_name)) {
+        return NULL;
+      }
+
+      if (!IsWhitelisted(socket_name)) {
+        ALOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd);
+        return NULL;
+      }
+
+      return new FileDescriptorInfo(fd);
+    }
+
+    // We only handle whitelisted regular files and character devices. Whitelisted
+    // character devices must provide a guarantee of sensible behaviour when
+    // reopened.
+    //
+    // S_ISDIR : Not supported. (We could if we wanted to, but it's unused).
+    // S_ISLINK : Not supported.
+    // S_ISBLK : Not supported.
+    // S_ISFIFO : Not supported. Note that the zygote uses pipes to communicate
+    // with the child process across forks but those should have been closed
+    // before we got to this point.
+    if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
+      ALOGE("Unsupported st_mode %d", f_stat.st_mode);
+      return NULL;
+    }
+
+    std::string file_path;
+    if (!Readlink(fd, &file_path)) {
+      return NULL;
+    }
+
+    if (!IsWhitelisted(file_path)) {
+      ALOGE("Not whitelisted : %s", file_path.c_str());
+      return NULL;
+    }
+
+    // File descriptor flags : currently on FD_CLOEXEC. We can set these
+    // using F_SETFD - we're single threaded at this point of execution so
+    // there won't be any races.
+    const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
+    if (fd_flags == -1) {
+      ALOGE("Failed fcntl(%d, F_GETFD) : %s", fd, strerror(errno));
+      return NULL;
+    }
+
+    // File status flags :
+    // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through
+    //   to the open() call.
+    //
+    // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can
+    //   do about these, since the file has already been created. We shall ignore
+    //   them here.
+    //
+    // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL
+    //   can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK.
+    //   In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for
+    //   their presence and pass them in to open().
+    int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
+    if (fs_flags == -1) {
+      ALOGE("Failed fcntl(%d, F_GETFL) : %s", fd, strerror(errno));
+      return NULL;
+    }
+
+    // File offset : Ignore the offset for non seekable files.
+    const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR));
+
+    // We pass the flags that open accepts to open, and use F_SETFL for
+    // the rest of them.
+    static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC);
+    int open_flags = fs_flags & (kOpenFlags);
+    fs_flags = fs_flags & (~(kOpenFlags));
+
+    return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset);
+  }
+
+  // Checks whether the file descriptor associated with this object
+  // refers to the same description.
+  bool Restat() const {
+    struct stat f_stat;
+    if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
+      return false;
+    }
+
+    return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev;
+  }
+
+  bool ReopenOrDetach() const {
+    if (is_sock) {
+      return DetachSocket();
+    }
+
+    // NOTE: This might happen if the file was unlinked after being opened.
+    // It's a common pattern in the case of temporary files and the like but
+    // we should not allow such usage from the zygote.
+    const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
+
+    if (new_fd == -1) {
+      ALOGE("Failed open(%s, %d) : %s", file_path.c_str(), open_flags, strerror(errno));
+      return false;
+    }
+
+    if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
+      close(new_fd);
+      ALOGE("Failed fcntl(%d, F_SETFD, %x) : %s", new_fd, fd_flags, strerror(errno));
+      return false;
+    }
+
+    if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
+      close(new_fd);
+      ALOGE("Failed fcntl(%d, F_SETFL, %x) : %s", new_fd, fs_flags, strerror(errno));
+      return false;
+    }
+
+    if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
+      close(new_fd);
+      ALOGE("Failed lseek64(%d, SEEK_SET) : %s", new_fd, strerror(errno));
+      return false;
+    }
+
+    if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) {
+      close(new_fd);
+      ALOGE("Failed dup2(%d, %d) : %s", fd, new_fd, strerror(errno));
+      return false;
+    }
+
+    close(new_fd);
+
+    return true;
+  }
+
+  const int fd;
+  const struct stat stat;
+  const std::string file_path;
+  const int open_flags;
+  const int fd_flags;
+  const int fs_flags;
+  const off_t offset;
+  const bool is_sock;
+
+ private:
+  FileDescriptorInfo(int fd) :
+    fd(fd),
+    stat(),
+    open_flags(0),
+    fd_flags(0),
+    fs_flags(0),
+    offset(0),
+    is_sock(true) {
+  }
+
+  FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
+                     int fd_flags, int fs_flags, off_t offset) :
+    fd(fd),
+    stat(stat),
+    file_path(file_path),
+    open_flags(open_flags),
+    fd_flags(fd_flags),
+    fs_flags(fs_flags),
+    offset(offset),
+    is_sock(false) {
+  }
+
+  // Returns true iff. a given path is whitelisted. A path is whitelisted
+  // if it belongs to the whitelist (see kPathWhitelist) or if it's a path
+  // under /system/framework that ends with ".jar".
+  static bool IsWhitelisted(const std::string& path) {
+    for (size_t i = 0; i < (sizeof(kPathWhitelist) / sizeof(kPathWhitelist[0])); ++i) {
+      if (kPathWhitelist[i] == path) {
+        return true;
+      }
+    }
+
+    static const std::string kFrameworksPrefix = "/system/framework/";
+    static const std::string kJarSuffix = ".jar";
+    if (path.compare(0, kFrameworksPrefix.size(), kFrameworksPrefix) == 0 &&
+        path.compare(path.size() - kJarSuffix.size(), kJarSuffix.size(), kJarSuffix) == 0) {
+      return true;
+    }
+    return false;
+  }
+
+  // TODO: Call android::base::Readlink instead of copying the code here.
+  static bool Readlink(const int fd, std::string* result) {
+    char path[64];
+    snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
+
+    // Code copied from android::base::Readlink starts here :
+
+    // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer,
+    // and truncates to whatever size you do supply, so it can't be used to query.
+    // We could call lstat first, but that would introduce a race condition that
+    // we couldn't detect.
+    // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here.
+    char buf[4096];
+    ssize_t len = readlink(path, buf, sizeof(buf));
+    if (len == -1) return false;
+
+    result->assign(buf, len);
+    return true;
+  }
+
+  // Returns the locally-bound name of the socket |fd|. Returns true
+  // iff. all of the following hold :
+  //
+  // - the socket's sa_family is AF_UNIX.
+  // - the length of the path is greater than zero (i.e, not an unnamed socket).
+  // - the first byte of the path isn't zero (i.e, not a socket with an abstract
+  //   address).
+  static bool GetSocketName(const int fd, std::string* result) {
+    sockaddr_storage ss;
+    sockaddr* addr = reinterpret_cast<sockaddr*>(&ss);
+    socklen_t addr_len = sizeof(ss);
+
+    if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) {
+      ALOGE("Failed getsockname(%d) : %s", fd, strerror(errno));
+      return false;
+    }
+
+    if (addr->sa_family != AF_UNIX) {
+      ALOGE("Unsupported socket (fd=%d) with family %d", fd, addr->sa_family);
+      return false;
+    }
+
+    const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(&ss);
+
+    size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path);
+    // This is an unnamed local socket, we do not accept it.
+    if (path_len == 0) {
+      ALOGE("Unsupported AF_UNIX socket (fd=%d) with empty path.", fd);
+      return false;
+    }
+
+    // This is a local socket with an abstract address, we do not accept it.
+    if (unix_addr->sun_path[0] == '\0') {
+      ALOGE("Unsupported AF_UNIX socket (fd=%d) with abstract address.", fd);
+      return false;
+    }
+
+    // If we're here, sun_path must refer to a null terminated filesystem
+    // pathname (man 7 unix). Remove the terminator before assigning it to an
+    // std::string.
+    if (unix_addr->sun_path[path_len - 1] ==  '\0') {
+      --path_len;
+    }
+
+    result->assign(unix_addr->sun_path, path_len);
+    return true;
+  }
+
+  bool DetachSocket() const {
+    const int dev_null_fd = open("/dev/null", O_RDWR);
+    if (dev_null_fd < 0) {
+      ALOGE("Failed to open /dev/null : %s", strerror(errno));
+      return false;
+    }
+
+    if (dup2(dev_null_fd, fd) == -1) {
+      ALOGE("Failed dup2 on socket descriptor %d : %s", fd, strerror(errno));
+      return false;
+    }
+
+    if (close(dev_null_fd) == -1) {
+      ALOGE("Failed close(%d) : %s", dev_null_fd, strerror(errno));
+      return false;
+    }
+
+    return true;
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
+};
+
+// A FileDescriptorTable is a collection of FileDescriptorInfo objects
+// keyed by their FDs.
+class FileDescriptorTable {
+ public:
+  // Creates a new FileDescriptorTable. This function scans
+  // /proc/self/fd for the list of open file descriptors and collects
+  // information about them. Returns NULL if an error occurs.
+  static FileDescriptorTable* Create() {
+    DIR* d = opendir(kFdPath);
+    if (d == NULL) {
+      ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
+      return NULL;
+    }
+    int dir_fd = dirfd(d);
+    dirent* e;
+
+    std::unordered_map<int, FileDescriptorInfo*> open_fd_map;
+    while ((e = readdir(d)) != NULL) {
+      const int fd = ParseFd(e, dir_fd);
+      if (fd == -1) {
+        continue;
+      }
+
+      FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd);
+      if (info == NULL) {
+        if (closedir(d) == -1) {
+          ALOGE("Unable to close directory : %s", strerror(errno));
+        }
+        return NULL;
+      }
+      open_fd_map[fd] = info;
+    }
+
+    if (closedir(d) == -1) {
+      ALOGE("Unable to close directory : %s", strerror(errno));
+      return NULL;
+    }
+    return new FileDescriptorTable(open_fd_map);
+  }
+
+  bool Restat() {
+    std::set<int> open_fds;
+
+    // First get the list of open descriptors.
+    DIR* d = opendir(kFdPath);
+    if (d == NULL) {
+      ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
+      return false;
+    }
+
+    int dir_fd = dirfd(d);
+    dirent* e;
+    while ((e = readdir(d)) != NULL) {
+      const int fd = ParseFd(e, dir_fd);
+      if (fd == -1) {
+        continue;
+      }
+
+      open_fds.insert(fd);
+    }
+
+    if (closedir(d) == -1) {
+      ALOGE("Unable to close directory : %s", strerror(errno));
+      return false;
+    }
+
+    return RestatInternal(open_fds);
+  }
+
+  // Reopens all file descriptors that are contained in the table. Returns true
+  // if all descriptors were successfully re-opened or detached, and false if an
+  // error occurred.
+  bool ReopenOrDetach() {
+    std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
+    for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
+      const FileDescriptorInfo* info = it->second;
+      if (info == NULL || !info->ReopenOrDetach()) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+ private:
+  FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map)
+      : open_fd_map_(map) {
+  }
+
+  bool RestatInternal(std::set<int>& open_fds) {
+    bool error = false;
+
+    // Iterate through the list of file descriptors we've already recorded
+    // and check whether :
+    //
+    // (a) they continue to be open.
+    // (b) they refer to the same file.
+    std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin();
+    while (it != open_fd_map_.end()) {
+      std::set<int>::const_iterator element = open_fds.find(it->first);
+      if (element == open_fds.end()) {
+        // The entry from the file descriptor table is no longer in the list
+        // of open files. We warn about this condition and remove it from
+        // the list of FDs under consideration.
+        //
+        // TODO(narayan): This will be an error in a future android release.
+        // error = true;
+        // ALOGW("Zygote closed file descriptor %d.", it->first);
+        it = open_fd_map_.erase(it);
+      } else {
+        // The entry from the file descriptor table is still open. Restat
+        // it and check whether it refers to the same file.
+        const bool same_file = it->second->Restat();
+        if (!same_file) {
+          // The file descriptor refers to a different description. We must
+          // update our entry in the table.
+          delete it->second;
+          it->second = FileDescriptorInfo::createFromFd(*element);
+          if (it->second == NULL) {
+            // The descriptor no longer no longer refers to a whitelisted file.
+            // We flag an error and remove it from the list of files we're
+            // tracking.
+            error = true;
+            it = open_fd_map_.erase(it);
+          } else {
+            // Successfully restatted the file, move on to the next open FD.
+            ++it;
+          }
+        } else {
+          // It's the same file. Nothing to do here. Move on to the next open
+          // FD.
+          ++it;
+        }
+
+        // Finally, remove the FD from the set of open_fds. We do this last because
+        // |element| will not remain valid after a call to erase.
+        open_fds.erase(element);
+      }
+    }
+
+    if (open_fds.size() > 0) {
+      // The zygote has opened new file descriptors since our last inspection.
+      // We warn about this condition and add them to our table.
+      //
+      // TODO(narayan): This will be an error in a future android release.
+      // error = true;
+      // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size());
+
+      // TODO(narayan): This code will be removed in a future android release.
+      std::set<int>::const_iterator it;
+      for (it = open_fds.begin(); it != open_fds.end(); ++it) {
+        const int fd = (*it);
+        FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd);
+        if (info == NULL) {
+          // A newly opened file is not on the whitelist. Flag an error and
+          // continue.
+          error = true;
+        } else {
+          // Track the newly opened file.
+          open_fd_map_[fd] = info;
+        }
+      }
+    }
+
+    return !error;
+  }
+
+  static int ParseFd(dirent* e, int dir_fd) {
+    char* end;
+    const int fd = strtol(e->d_name, &end, 10);
+    if ((*end) != '\0') {
+      return -1;
+    }
+
+    // Don't bother with the standard input/output/error, they're handled
+    // specially post-fork anyway.
+    if (fd <= STDERR_FILENO || fd == dir_fd) {
+      return -1;
+    }
+
+    return fd;
+  }
+
+  // Invariant: All values in this unordered_map are non-NULL.
+  std::unordered_map<int, FileDescriptorInfo*> open_fd_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileDescriptorTable);
+};
diff --git a/docs/html/topic/libraries/support-library/revisions.jd b/docs/html/topic/libraries/support-library/revisions.jd
index 1fe4daa..4b743d5 100644
--- a/docs/html/topic/libraries/support-library/revisions.jd
+++ b/docs/html/topic/libraries/support-library/revisions.jd
@@ -197,8 +197,17 @@
   <li>{@link android.support.design.widget.Snackbar} now draws behind the
   navigation bar if the status bar is translucent.
   </li>
+
 </ul>
 
+<h4>MediaRouter library</h4>
+
+<p>
+  Bluetooth devices are no longer listed as media routes. Routing audio to
+  Bluetooth devices is now solely controlled at the Android system level.
+</p>
+
+
 <h3 id="24-2-0-deprecations">Deprecations</h3>
 
 <p>Deprecated classes and methods are subject to removal in a future release. You should migrate away from these APIs as soon as possible.</p>
diff --git a/docs/html/training/basics/firstapp/building-ui.jd b/docs/html/training/basics/firstapp/building-ui.jd
index a680c73..6f321e9 100644
--- a/docs/html/training/basics/firstapp/building-ui.jd
+++ b/docs/html/training/basics/firstapp/building-ui.jd
@@ -71,17 +71,17 @@
 <h2 id="LinearLayout">Create a Linear Layout</h2>
 
 <ol>
-  <li>From the <code>res/layout/</code> directory, open the
-    <code>activity_main.xml</code> file.
+  <li>In Android Studio's <b>Project</b> window, open <b>app > res >
+    layout > activity_main.xml</b>.
     <p>This XML file defines the layout of your activity. It contains the
       default "Hello World" text view.</p>
   </li>
   <li>When you open a layout file, you’re first shown the design editor in the
     <a href="/studio/write/layout-editor.html">Layout Editor</a>. For this lesson,
-    you work directly with the XML, so click the <b>Text</b> tab to switch to
-    the text editor.
+    you work directly with the XML, so click the <b>Text</b> tab at the bottom
+    of the window to switch to the text editor.
   </li>
-  <li>Replace the contents of the file with the following XML:
+  <li>Delete everything and insert the following XML:
     <pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
 &lt;LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
@@ -138,6 +138,9 @@
 &lt;/LinearLayout&gt;
 </pre>
 
+<p>Don't worry about the error that appears for
+<code>&#64;string/edit_message</code>; you'll fix that soon.</p>
+
 <p>Here is a description of the attributes in the
   {@link android.widget.EditText &lt;EditText>} you added:</p>
 
@@ -157,7 +160,7 @@
   <p>A resource object is a unique integer name that's associated with an app resource,
 such as a bitmap, layout file, or string.</p>
   <p>Every resource has a
-corresponding resource object defined in your project's {@code gen/R.java} file. You can use the
+corresponding resource object defined in your project's {@code R.java} file. You can use the
 object names in the {@code R} class to refer to your resources, such as when you need to specify a
 string value for the <a
 href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">{@code android:hint}</a>
@@ -174,7 +177,7 @@
 <p>The plus sign (<code>+</code>) before the resource type is needed only when you're defining a
 resource ID for the first time. When you compile the app,
 the SDK tools use the ID name to create a new resource ID in
-your project's {@code gen/R.java} file that refers to the {@link
+your project's {@code R.java} file that refers to the {@link
 android.widget.EditText} element. With the resource ID declared once this way,
 other references to the ID do not
 need the plus sign. Using the plus sign is necessary only when specifying a new resource ID and not
@@ -211,10 +214,10 @@
 <h2 id="Strings">Add String Resources</h2>
 
 <p>By default, your Android project includes a string resource file at
-<code>res/values/strings.xml</code>. Here, you'll add two new strings.</p>
+<b>res > values > strings.xml</b>. Here, you'll add two new strings.</p>
 
 <ol>
-<li>From the <code>res/values/</code> directory, open <code>strings.xml</code>.</li>
+<li>From the <b>Project</b> window, open <b>res > values > strings.xml</b>.</li>
 <li>Add two strings so that your file looks like this:
 <pre>&lt;?xml version="1.0" encoding="utf-8"?>
 &lt;resources>
@@ -340,15 +343,12 @@
 
 <h2>Run Your App</h2>
 
-<p>This layout is applied by the default {@link android.app.Activity} class
-that the SDK tools generated when you created the project.</p>
-
-<p>To run the app and see the results,
-  click <strong>Run 'app'</strong>
+<p>To see how the app now looks on your device or emulator,
+  click <strong>Run</strong>
     <img src="{@docRoot}images/tools/as-run.png"
     style="vertical-align:baseline;margin:0; max-height:1em" /> in the
     toolbar.</p>
 
-<p>Continue to the <a href="starting-activity.html">next
-lesson</a> to learn how to respond to button presses, read content
-from the text field, start another activity, and more.</p>
\ No newline at end of file
+<p>To add app behaviors such as responding to a button and starting
+another activity, continue to the <a href="starting-activity.html">next
+lesson</a>.</p>
\ No newline at end of file
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index cad32bf..60be5f6 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -31,129 +31,71 @@
 <ol>
   <li>In Android Studio, create a new project:
     <ul>
-      <li>If you don't have a project opened, in the <strong>Welcome</strong> screen, click <strong>
-        New Project</strong>.</li>
-      <li>If you have a project opened, from the <strong>File</strong> menu, select <strong>New
-        Project</strong>. The <em>Create New Project</em> screen appears.</li>
+      <li>If you don't have a project opened, in the <strong>Welcome to Android Studio</strong> window, click <strong>
+        Start a new Android Studio project</strong>.</li>
+      <li>If you have a project opened, select <strong>File > New Project</strong>.</li>
     </ul>
   </li>
-  <li>Fill out the fields on the screen. For <strong>Application Name</strong>
-    use "My First App". For <strong>Company Domain</strong>, use "example.com".
-    For the other fields, use the default values and click <strong>Next</strong>
-    <p>Here's a brief explanation of each field:</p>
+  <li>In the <b>New Project</b> screen, enter the following values:</p>
     <ul>
-      <li><strong>Application Name</strong> is the app name that appears to users.</li>
-      <li><strong>Company domain</strong> provides a qualifier that will be appended to the package
-        name; Android Studio will remember this qualifier for each new project you create.</li>
-      <li><strong>Package name</strong> is the fully qualified name for the project (following the
-        same rules as those for naming packages in the Java programming language). Your package name
-        must be unique across all packages installed on the Android system. You can <strong>
-        Edit</strong> this value independently from the application name or the company
-        domain.</li>
-      <li><strong>Project location</strong> is the directory on your system that holds the project
-        files.</li>
+      <li><strong>Application Name</strong>: "My First App" </li>
+      <li><strong>Company Domain</strong>: "example.com"</li>
     </ul>
+    <p>Android Studio fills in the package name and project location for you,
+    but you can edit these if you'd like.
   </li>
-  <li>Under <strong>Target Android Devices</strong>, accept the default values
-    and click <strong>Next</strong>.
-    <p>The Minimum Required SDK is the earliest version of Android that your app supports,
-      indicated using the <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">
+  <li>Click <b>Next</b>.</li>
+  <li>In the <b>Target Android Devices</b> screen, keep the default values and
+    click <b>Next</b>.
+    <p>The <b>Minimum Required SDK</b> is the earliest version of Android that your app supports,
+      which is indicated by the <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">
       API level</a>. To support as many devices as possible, you should set this to the lowest
       version available that allows your app to provide its core feature set. If any feature of your
-      app is possible only on newer versions of Android and it's not critical to the app's core
-      feature set, you can enable the feature only when running on the versions that support it (as
-      discussed in <a href="{@docRoot}training/basics/supporting-devices/platforms.html">
+      app is possible only on newer versions of Android and it's not critical to the core
+      feature set, enable that feature only when running on the versions that support it (see
+      <a href="{@docRoot}training/basics/supporting-devices/platforms.html">
       Supporting Different Platform Versions</a>).</p>
     </li>
 
-  <li>Under <strong>Add an Activity to Mobile</strong>, select <strong>Empty
+  <li>In the <strong>Add an Activity to Mobile</strong> screen, select <strong>Empty
     Activity</strong> and click <strong>Next</strong>.
   </li>
 
-  <div class="sidebox-wrapper">
-    <div class="sidebox">
-      <h3>Activities</h3>
-      <p>An activity is one of the distinguishing features of the Android framework. Activities
-        provide the user with access to your app, and there may be many activities. An application
-        will usually have a main activity for when the user launches the application, another
-        activity for when she selects some content to view, for example, and other activities for
-        when she performs other tasks within the app. See <a href="{@docRoot}guide/components/activities.html">
-        Activities</a> for more information.</p>
-    </div>
-  </div>
-
-  <li>Under <strong>Customize the Activity</strong>, accept the default values
+  <li>In the <strong>Customize the Activity</strong> screen, keep the default values
     and click <strong>Finish</strong>.
 </ol>
 
-<p>Your Android project is now a basic "Hello World" app that contains some default files. Take a
-moment to review the most important of these:</p>
+<p>After some processing, Android Studio opens and displays a "Hello World" app
+with default files. You will add functionality to some of
+these files in the following lessons.</p>
+
+<p>Now take a moment to review the most important files. First, be sure that
+the <b>Project</b> window is open (select <b>View > Tool Windows > Project</b>)
+and the <b>Android</b> view is selected from the drop-down list at the top.
+You can then see the following files:</p>
 
 <dl>
-  <dt><code>app/src/main/java/com.example.myfirstapp/MainActivity.java</code></dt>
+  <dt><b>app > java > com.example.myfirstapp > MainActivity.java</b></dt>
   <dd>This file appears in Android Studio after the New Project wizard finishes.
     It contains the class definition for the activity you created earlier. When you build
     and run the app, the {@link android.app.Activity} starts and loads the
     layout file that says "Hello World!"</dd>
 
-  <dt><code>app/src/main/res/layout/activity_main.xml</code></dt>
+  <dt><b>app > res > layout > activity_main.xml</b></dt>
   <dd>This XML file defines the layout of the activity. It contains a {@code TextView}
     element with the text "Hello world!".</dd>
 
-  <dt><code>app/src/main/AndroidManifest.xml</code></dt>
+  <dt><b>app > manifests > AndroidManifest.xml</b></dt>
   <dd>The <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest file</a> describes
     the fundamental characteristics of the app and defines each of its components. You'll revisit
     this file as you follow these lessons and add more components to your app.</dd>
-  <dt><code>app/build.gradle</code></dt>
+
+  <dt><b>Gradle Scripts > build.gradle</b></dt>
   <dd>Android Studio uses Gradle to compile and build your app. There is a <code>build.gradle</code>
     file for each module of your project, as well as a <code>build.gradle</code> file for the entire
-    project. Usually, you're only interested in the <code>build.gradle</code> file for the module,
-    in this case the <code>app</code> or application module. This is where your app's build dependencies
-    are set, including the <code>defaultConfig</code> settings:
-    <ul>
-      <li><code>compiledSdkVersion</code> is the platform version against which you will compile
-        your app. By default, this is set to the latest version of Android available in your SDK.
-        By default, this is set to the latest version of Android SDK installed on your
-        development machine.
-        You can still build your app to support older versions, but setting this to the latest
-        version allows you to enable new features and optimize your app for a great user experience
-        on the latest devices.</li>
-      <li><code>applicationId</code> is the fully qualified package name for your application that
-        you specified in the New Project wizard.</li>
-      <li><code>minSdkVersion</code> is the Minimum SDK version you specified during the New Project
-        wizard. This is the earliest version of the Android SDK that your app supports.</li>
-      <li><code>targetSdkVersion</code> indicates the highest version of Android with which you have
-        tested your application. As new versions of Android become available, you should
-        test your app on the new version and update this value to match the latest API level and
-        thereby take advantage of new platform features. For more information, read
-        <a href="{@docRoot}training/basics/supporting-devices/platforms.html">Supporting Different
-          Platform Versions</a>.</li>
-    </ul>
-    <p>See <a href="{@docRoot}studio/build/index.html">Building Your Project with Gradle</a>
-    for more information about Gradle.</p></dd>
-</dl>
-
-<p>Note also the <code>/res</code> subdirectories that contain the
-<a href="{@docRoot}guide/topics/resources/overview.html">resources</a> for your application:</p>
-<dl>
-  <dt><code>drawable<em>-&lt;density&gt;</em>/</code></dt>
-    <dd>Directories for <a href="{@docRoot}guide/topics/resources/drawable-resource.html">
-    drawable resources</a>, other than launcher icons, designed
-    for various <a href="{@docRoot}training/multiscreen/screendensities.html">densities</a>.
-</dd>
-  <dt><code>layout/</code></dt>
-    <dd>Directory for files that define your app's user interface like {@code activity_main.xml},
-      discussed above, which describes a basic layout for the {@code MainActivity}
-      class.</dd>
-  <dt><code>menu/</code></dt>
-    <dd>Directory for files that define your app's menu items.</dd>
-  <dt><code>mipmap/</code></dt>
-    <dd>Launcher icons reside in the {@code mipmap/} folder rather than the
-    {@code drawable/} folders. This folder contains the {@code ic_launcher.png} image
-    that appears when you run the default app.</dd>
-  <dt><code>values/</code></dt>
-    <dd>Directory for other XML files that contain a collection of resources, such as
-      string and color definitions.</dd>
+    project. Usually, you're only interested in the <code>build.gradle</code> file for the module.
+    in this case the <code>app</code> or application module. For more information about this file,
+    see <a href="{@docRoot}studio/build/index.html">Building Your Project with Gradle</a>.</dd>
 </dl>
 
 <p>
diff --git a/docs/html/training/basics/firstapp/running-app.jd b/docs/html/training/basics/firstapp/running-app.jd
index e809871..085849f 100755
--- a/docs/html/training/basics/firstapp/running-app.jd
+++ b/docs/html/training/basics/firstapp/running-app.jd
@@ -3,9 +3,7 @@
 parent.link=index.html
 
 trainingnavtop=true
-
 page.tags=emulator
-helpoutsWidget=true
 
 @jd:body
 
@@ -18,7 +16,7 @@
 
 <ol>
   <li><a href="#RealDevice">Run on a Real Device</a></li>
-  <li><a href="#Emulator">Run on the Emulator</a></li>
+  <li><a href="#Emulator">Run on an Emulator</a></li>
 </ol>
 
 <h2>You should also read</h2>
@@ -34,8 +32,10 @@
 
 
 <p>In the <a href="creating-project.html">previous lesson</a>, you created an
-  Android project. The project contains a default app that displays
-  "Hello World". In this lesson, you will run the app on a device or emulator.</p>
+Android project that displays "Hello World." You can now run the app on a real
+device or on an emulator. If you don't have a real device available, skip to
+<a href="#Emulator">Run on an Emulator</a>.</p>
+
 
 <h2 id="RealDevice">Run on a Real Device</h2>
 
@@ -68,7 +68,7 @@
 <p>Android Studio installs the app on your connected device and starts it.</p>
 
 
-<h2 id="Emulator">Run on the Emulator</h2>
+<h2 id="Emulator">Run on an Emulator</h2>
 
 <p>Before you run your app on an emulator, you need to create an
   <a href="{@docRoot}tools/devices/index.html">Android Virtual Device</a> (AVD)
@@ -82,12 +82,14 @@
     <strong>Tools &gt; Android &gt; AVD Manager</strong>, or by clicking
     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>On the AVD Manager main screen, click <strong>Create Virtual Device</strong>.</li>
-  <li>In the Select Hardware page, select a phone device, such as Nexus 6,
-    then click <strong>Next</strong>.
+  <li>In the <b>Your Virtual Devices</b> screen, click <strong>Create Virtual Device</strong>.</li>
+  <li>In the <b>Select Hardware</b> screen, select a phone device, such as Nexus 6,
+    and then click <strong>Next</strong>.
   </li>
-  <li>In the Select Image page, choose the desired system image for the AVD and
+  <li>In the <b>System Image</b> screen, choose the desired system image for the AVD and
     click <strong>Next</strong>.
+    <p>If you don't have a particular system image installed,
+    you can get it by clicking the <b>download</b> link.</p>
   </li>
   <li>Verify the configuration settings (for your first AVD, leave all the
     settings as they are), and then click <strong>Finish</strong>.
diff --git a/docs/html/training/basics/firstapp/starting-activity.jd b/docs/html/training/basics/firstapp/starting-activity.jd
index ebf42cb..4385d13 100644
--- a/docs/html/training/basics/firstapp/starting-activity.jd
+++ b/docs/html/training/basics/firstapp/starting-activity.jd
@@ -38,7 +38,7 @@
 <h2 id="RespondToButton">Respond to the Send Button</h2>
 
 <ol>
-  <li>In the file <code>res/layout/activity_main.xml</code>, add the
+  <li>In the file <b>res > layout > activity_main.xml</b>, add the
     <a href="{@docRoot}reference/android/view/View.html#attr_android:onClick">{@code android:onClick}</a>
     attribute to the {@link android.widget.Button &lt;Button&gt;} element as
     shown below:
@@ -52,7 +52,7 @@
       method in your activity whenever a user clicks on the button.</p>
   </li>
 
-  <li>In the file <code>java/com.example.myfirstapp/MainActivity.java</code>,
+  <li>In the file <b>java > com.example.myfirstapp > MainActivity.java</b>,
     add the <code>sendMessage()</code> method stub as shown below:
 
     <pre>public class MainActivity extends AppCompatActivity {
@@ -85,7 +85,9 @@
 <p>Next, you’ll fill in this method to read the contents of the text field and deliver that text to
 another activity.</p>
 
+
 <h2 id="BuildIntent">Build an Intent</h2>
+
 <p>An {@link android.content.Intent} is an object that provides runtime binding
   between separate components (such as two activities). The
   {@link android.content.Intent} represents an app’s "intent to do something."
@@ -113,13 +115,22 @@
     }
 }</pre>
 
-<p class="note"><strong>Note: </strong>Android Studio will display
-  <code>Cannot resolve symbol</code> errors because the code references classes
-  like {@link android.content.Intent} and {@link android.widget.EditText}
-  that have not been imported. To import these classes, you can either 1)
-  use Android Studio's "import class" functionality by pressing Alt + Enter
-  (Option + Return on Mac) or 2) manually add import statements at the top of
-  the file.</p>
+<p>Android Studio will display <b>Cannot
+resolve symbol</b> errors because this code references classes that are not
+imported. You can solve some of these with Android Studio's "import class"
+functionality by pressing Alt + Enter (or Option + Return on Mac).
+Your imports should end up as the following:</p>
+<pre>
+import android.content.Intent;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.EditText;
+</pre>
+
+<p>An error remains for <code>DisplayMessageActivity</code>, but that's okay;
+you'll fix that in the next section.
+
 
 <p>There’s a lot going on in <code>sendMessage()</code>, so let’s explain
   what's going on.</p>
@@ -150,6 +161,7 @@
   method starts an instance of the <code>DisplayMessageActivity</code> specified
   by the {@link android.content.Intent}. Now you need to create the class.</p>
 
+
 <h2 id="CreateActivity">Create the Second Activity</h2>
 
 <ol>
@@ -169,7 +181,8 @@
   <li>Creates the corresponding layout file <code>activity_display_message.xml</code>
     </li>
   <li>Adds the required
-    <a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a>
+    <a href="{@docRoot}guide/topics/manifest/activity-element.html"
+    ><code>&lt;activity&gt;</code></a>
     element in <code>AndroidManifest.xml</code>.
 </ul>
 
@@ -199,7 +212,16 @@
    layout.addView(textView);
 }</pre>
   </li>
-  <li>Press Alt + Enter (option + return on Mac) to import missing classes.</li>
+  <li>Press Alt + Enter (or Option + Return on Mac) to import missing classes.
+  Your imports should end up as the following:
+<pre>
+import android.content.Intent;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.widget.TextView;
+</pre>
+</li>
 </ol>
 
 <p>There’s a lot going on here, so let’s explain:</p>