Merge remote-tracking branch 'aosp/upstream-master' into merge

Conflicts:
	.idea/libraries/asm_tools.xml
	.idea/libraries/bouncy_castle.xml
	.idea/libraries/builder_model.xml
	.idea/libraries/commons_compress.xml
	.idea/libraries/easymock_tools.xml
	.idea/libraries/freemarker_2_3_20.xml
	.idea/libraries/guava_tools.xml
	.idea/libraries/kxml2.xml
	.idea/libraries/lombok_ast.xml
	.idea/libraries/mockito.xml
	.idea/modules.xml
	.idea/vcs.xml
	build/scripts/layouts.gant
	updater/src/com/intellij/updater/Runner.java

Change-Id: I8e1c173e00cd76c855b8a98543b0a0edfdd99d12
diff --git a/.gitignore b/.gitignore
index 3fb1a17..78fbd0b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,8 @@
 /python/helpers/python-skeletons
 /test-system
 /test-config
+.jps-build-data
+/bin/build-log.xml
+/bin/build.log
+/androidStudio
+/build/TEST*
diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
old mode 100644
new mode 100755
index 5593bda..2faab0e
--- a/.idea/codeStyleSettings.xml
+++ b/.idea/codeStyleSettings.xml
@@ -51,6 +51,7 @@
             <option name="USE_RELATIVE_INDENTS" value="false" />
           </value>
         </option>
+        <option name="LINE_SEPARATOR" value="&#10;" />
         <option name="FIELD_NAME_PREFIX" value="my" />
         <option name="STATIC_FIELD_NAME_PREFIX" value="our" />
         <option name="RIGHT_MARGIN" value="140" />
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index bb168e8..7885bf8 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -57,6 +57,7 @@
     <option name="DEPRECATION" value="false" />
   </component>
   <component name="JavacSettings">
+    <option name="DEPRECATION" value="false" />
     <option name="MAXIMUM_HEAP_SIZE" value="400" />
   </component>
 </project>
diff --git a/.idea/copyright/aosp.xml b/.idea/copyright/aosp.xml
new file mode 100644
index 0000000..077aec6
--- /dev/null
+++ b/.idea/copyright/aosp.xml
@@ -0,0 +1,9 @@
+<component name="CopyrightManager">
+  <copyright>
+    <option name="notice" value="Copyright (C) &amp;#36;today.year The Android Open Source Project&#10;&#10;Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#10;you may not use this file except in compliance with the License.&#10;You may obtain a copy of the License at&#10;&#10;     http://www.apache.org/licenses/LICENSE-2.0&#10;&#10;Unless required by applicable law or agreed to in writing, software&#10;distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#10;WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#10;See the License for the specific language governing permissions and&#10;limitations under the License." />
+    <option name="keyword" value="Copyright" />
+    <option name="allowReplaceKeyword" value="" />
+    <option name="myName" value="aosp" />
+    <option name="myLocal" value="true" />
+  </copyright>
+</component>
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
index 19fba77..7d505fe 100644
--- a/.idea/copyright/profiles_settings.xml
+++ b/.idea/copyright/profiles_settings.xml
@@ -1,5 +1,8 @@
 <component name="CopyrightManager">
-  <settings default="apache 2 license">
+  <settings default="aosp">
+    <module2copyright>
+      <element module="aosp-code" copyright="aosp" />
+    </module2copyright>
     <LanguageOptions name="__TEMPLATE__">
       <option name="addBlankAfter" value="false" />
     </LanguageOptions>
diff --git a/.idea/dictionaries/adt.xml b/.idea/dictionaries/adt.xml
new file mode 100644
index 0000000..7be8565
--- /dev/null
+++ b/.idea/dictionaries/adt.xml
@@ -0,0 +1,326 @@
+<component name="ProjectDictionaryState">
+  <dictionary name="adt">
+    <words>
+      <w>&amp;amp</w>
+      <w>aapt</w>
+      <w>aarrggbb</w>
+      <w>accessors</w>
+      <w>actionbar</w>
+      <w>adb's</w>
+      <w>adbhost</w>
+      <w>addon</w>
+      <w>addons</w>
+      <w>addr</w>
+      <w>aidl</w>
+      <w>aload</w>
+      <w>androiddebugkey</w>
+      <w>anim</w>
+      <w>aosp</w>
+      <w>apkbuilder</w>
+      <w>apos</w>
+      <w>appname</w>
+      <w>areturn</w>
+      <w>argb</w>
+      <w>argv</w>
+      <w>armeabi</w>
+      <w>ast's</w>
+      <w>async</w>
+      <w>attrs</w>
+      <w>autofocus</w>
+      <w>automator</w>
+      <w>avd's</w>
+      <w>avdname</w>
+      <w>backfill</w>
+      <w>basename</w>
+      <w>basenames</w>
+      <w>bicubic</w>
+      <w>bilinear</w>
+      <w>bindir</w>
+      <w>bipush</w>
+      <w>bitcodelib</w>
+      <w>bitmask</w>
+      <w>blockquote</w>
+      <w>bluetooth</w>
+      <w>booleans</w>
+      <w>bootloader</w>
+      <w>borderless</w>
+      <w>bytecode</w>
+      <w>calloc</w>
+      <w>charsets</w>
+      <w>checkable</w>
+      <w>chksum</w>
+      <w>classfile</w>
+      <w>classname</w>
+      <w>classpathentry</w>
+      <w>clinit</w>
+      <w>clipart</w>
+      <w>closeables</w>
+      <w>codenames</w>
+      <w>combineaccessrules</w>
+      <w>compat</w>
+      <w>configurables</w>
+      <w>conv</w>
+      <w>crlf</w>
+      <w>crypto</w>
+      <w>cygpath</w>
+      <w>cygwin</w>
+      <w>dalvik</w>
+      <w>darcula</w>
+      <w>ddmlib</w>
+      <w>ddms</w>
+      <w>debuggable</w>
+      <w>densityless</w>
+      <w>designtime</w>
+      <w>dest</w>
+      <w>dexdump</w>
+      <w>digester</w>
+      <w>dimen</w>
+      <w>dirname</w>
+      <w>disp</w>
+      <w>donottranslate</w>
+      <w>dpad</w>
+      <w>drawables</w>
+      <w>dropdown</w>
+      <w>dumpsys</w>
+      <w>eabi</w>
+      <w>easymock</w>
+      <w>emdash</w>
+      <w>endian</w>
+      <w>enqueued</w>
+      <w>errno</w>
+      <w>executables</w>
+      <w>expectedly</w>
+      <w>filenames</w>
+      <w>filepath</w>
+      <w>fixme</w>
+      <w>fqcn</w>
+      <w>framebuffer</w>
+      <w>frameworkdir</w>
+      <w>froyo</w>
+      <w>fwvga</w>
+      <w>gbdserver</w>
+      <w>gdbserver</w>
+      <w>genkey</w>
+      <w>getenv</w>
+      <w>getfield</w>
+      <w>getprop</w>
+      <w>getstatic</w>
+      <w>globbing</w>
+      <w>goto</w>
+      <w>gradle</w>
+      <w>guide's</w>
+      <w>guillemets</w>
+      <w>hardcode</w>
+      <w>hardcoding</w>
+      <w>hashcode</w>
+      <w>hdpi</w>
+      <w>holo</w>
+      <w>horiz</w>
+      <w>httpclient</w>
+      <w>hvga</w>
+      <w>iaload</w>
+      <w>iastore</w>
+      <w>iconst</w>
+      <w>inflater</w>
+      <w>infos</w>
+      <w>inlined</w>
+      <w>innerclass</w>
+      <w>inputfile</w>
+      <w>insn</w>
+      <w>instantiatable</w>
+      <w>instrumentations</w>
+      <w>intelli</w>
+      <w>interpolator</w>
+      <w>ints</w>
+      <w>invokestatic</w>
+      <w>invokevirtual</w>
+      <w>ipsum</w>
+      <w>ireturn</w>
+      <w>iterable</w>
+      <w>jarfile</w>
+      <w>jarlist</w>
+      <w>jarpath</w>
+      <w>javabuilder</w>
+      <w>javanature</w>
+      <w>jdwp</w>
+      <w>jpeg</w>
+      <w>junit</w>
+      <w>keepclasseswithmembernames</w>
+      <w>keepclasseswithmembers</w>
+      <w>keygen</w>
+      <w>keypass</w>
+      <w>keysexposed</w>
+      <w>keyshidden</w>
+      <w>keyssoft</w>
+      <w>keystore</w>
+      <w>keytool</w>
+      <w>kxml</w>
+      <w>landroid</w>
+      <w>layoublib</w>
+      <w>layoutlib</w>
+      <w>layoutlibs</w>
+      <w>layoutopt</w>
+      <w>layoutrules</w>
+      <w>ldltr</w>
+      <w>ldpi</w>
+      <w>ldrtl</w>
+      <w>levenshtein</w>
+      <w>lexing</w>
+      <w>libc</w>
+      <w>licensable</w>
+      <w>licensor</w>
+      <w>linenumber</w>
+      <w>ljava</w>
+      <w>lombok</w>
+      <w>lookups</w>
+      <w>lookupswitch</w>
+      <w>looper</w>
+      <w>lorem</w>
+      <w>lpackage</w>
+      <w>makefile</w>
+      <w>malloc</w>
+      <w>manifestmerger</w>
+      <w>manifmerger</w>
+      <w>mdpi</w>
+      <w>memalign</w>
+      <w>minsdk</w>
+      <w>mipmap</w>
+      <w>mkdirs</w>
+      <w>monospace</w>
+      <w>moreunit</w>
+      <w>multimap</w>
+      <w>multipart</w>
+      <w>multitouch</w>
+      <w>nano</w>
+      <w>nativelib</w>
+      <w>navexposed</w>
+      <w>navhidden</w>
+      <w>ninepatch</w>
+      <w>nodpi</w>
+      <w>nokeys</w>
+      <w>nonav</w>
+      <w>notlong</w>
+      <w>notnight</w>
+      <w>notouch</w>
+      <w>nullable</w>
+      <w>nulling</w>
+      <w>nullness</w>
+      <w>objectweb</w>
+      <w>opcode</w>
+      <w>opcodes</w>
+      <w>pathname</w>
+      <w>picasa</w>
+      <w>plugin's</w>
+      <w>png's</w>
+      <w>prebuilts</w>
+      <w>prefs</w>
+      <w>preload</w>
+      <w>prepending</w>
+      <w>printf</w>
+      <w>println</w>
+      <w>proc</w>
+      <w>prog</w>
+      <w>progdir</w>
+      <w>programmatically</w>
+      <w>proguard</w>
+      <w>prolog</w>
+      <w>qemu</w>
+      <w>quickfix</w>
+      <w>quickstart</w>
+      <w>qvga</w>
+      <w>rasterize</w>
+      <w>rasterizer</w>
+      <w>realloc</w>
+      <w>recurse</w>
+      <w>reflow</w>
+      <w>reformats</w>
+      <w>reimplement</w>
+      <w>renderscript</w>
+      <w>reparse</w>
+      <w>requestor</w>
+      <w>resampling</w>
+      <w>resizability</w>
+      <w>resized</w>
+      <w>revalidate</w>
+      <w>rrggbb</w>
+      <w>sccs</w>
+      <w>screenshot</w>
+      <w>scroller</w>
+      <w>scrollview</w>
+      <w>sdcard</w>
+      <w>sdk's</w>
+      <w>sdkbin</w>
+      <w>sdklib</w>
+      <w>sdkman</w>
+      <w>sdks</w>
+      <w>serialnumber</w>
+      <w>severities</w>
+      <w>sparsearray</w>
+      <w>sqrt</w>
+      <w>stacktrace</w>
+      <w>stderr</w>
+      <w>stdout</w>
+      <w>stopship</w>
+      <w>storepass</w>
+      <w>storetype</w>
+      <w>styleable</w>
+      <w>subclassed</w>
+      <w>subclassing</w>
+      <w>subfolder</w>
+      <w>submenu</w>
+      <w>superset</w>
+      <w>sysdir</w>
+      <w>sysimg</w>
+      <w>targetsdk</w>
+      <w>testcase</w>
+      <w>testroot</w>
+      <w>testsuite</w>
+      <w>tmpdir</w>
+      <w>traceview</w>
+      <w>tuple</w>
+      <w>tvdpi</w>
+      <w>uiautomator</w>
+      <w>uname</w>
+      <w>unarchive</w>
+      <w>unary</w>
+      <w>uncapitalized</w>
+      <w>uncompressing</w>
+      <w>unescape</w>
+      <w>unescaping</w>
+      <w>unformatted</w>
+      <w>unlocalized</w>
+      <w>unmanages</w>
+      <w>unregister</w>
+      <w>unregisters</w>
+      <w>userdata</w>
+      <w>versioncode</w>
+      <w>vert</w>
+      <w>viewport</w>
+      <w>vmsig</w>
+      <w>wakelock</w>
+      <w>wakelocks</w>
+      <w>wakeup</w>
+      <w>webkit</w>
+      <w>wikipedia</w>
+      <w>workdir</w>
+      <w>wqvga</w>
+      <w>writeable</w>
+      <w>wvga</w>
+      <w>xdpi</w>
+      <w>xerces</w>
+      <w>xfermode</w>
+      <w>xhdpi</w>
+      <w>xhigh</w>
+      <w>xlarge</w>
+      <w>xliff</w>
+      <w>xmlns</w>
+      <w>xxhdpi</w>
+      <w>xxhigh</w>
+      <w>xxxhdpi</w>
+      <w>xxxhigh</w>
+      <w>ydpi</w>
+      <w>yyyy</w>
+      <w>zipalign</w>
+    </words>
+  </dictionary>
+</component>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml
index 63323b4..c9f9460 100644
--- a/.idea/inspectionProfiles/idea_default.xml
+++ b/.idea/inspectionProfiles/idea_default.xml
@@ -50,7 +50,7 @@
     <inspection_tool class="ConstantConditionalExpressionJS" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ConstantConditions" enabled="true" level="WARNING" enabled_by_default="true">
       <scope name="runtime.classes" level="WARNING" enabled="false">
-        <option name="SUGGEST_NULLABLE_ANNOTATIONS" value="false" />
+        <option name="SUGGEST_NULLABLE_ANNOTATIONS" value="true" />
         <option name="DONT_REPORT_TRUE_ASSERT_STATEMENTS" value="false" />
       </scope>
       <option name="SUGGEST_NULLABLE_ANNOTATIONS" value="true" />
@@ -318,6 +318,10 @@
     <inspection_tool class="MethodNamesDifferOnlyByCase" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="MethodOverloadsParentMethod" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="MethodOverridesStaticMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MissingOverrideAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="ignoreObjectMethods" value="true" />
+      <option name="ignoreAnonymousClassMethods" value="false" />
+    </inspection_tool>
     <inspection_tool class="MisspelledCompareTo" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="MisspelledEquals" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="MisspelledHashcode" enabled="true" level="WARNING" enabled_by_default="true" />
@@ -563,7 +567,7 @@
     <inspection_tool class="UnnecessaryEnumModifier" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="UnnecessaryFullyQualifiedName" enabled="true" level="WARNING" enabled_by_default="true">
       <scope name="Tests" level="WARNING" enabled="false">
-        <option name="m_ignoreJavadoc" value="false" />
+        <option name="m_ignoreJavadoc" value="true" />
       </scope>
       <option name="m_ignoreJavadoc" value="true" />
     </inspection_tool>
diff --git a/.idea/libraries/asm_tools.xml b/.idea/libraries/asm_tools.xml
index 9435a42..6009e9f 100644
--- a/.idea/libraries/asm_tools.xml
+++ b/.idea/libraries/asm_tools.xml
@@ -1,11 +1,13 @@
 <component name="libraryTable">
   <library name="asm-tools">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/android/android/lib/asm-4.0.jar!/" />
-      <root url="jar://$PROJECT_DIR$/android/android/lib/asm-analysis-4.0.jar!/" />
-      <root url="jar://$PROJECT_DIR$/android/android/lib/asm-tree-4.0.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/asm-tools/asm-4.0.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/asm-tools/asm-analysis-4.0.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/asm-tools/asm-tree-4.0.jar!/" />
     </CLASSES>
     <JAVADOC />
-    <SOURCES />
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/asm-tools/src-4.0.zip!/" />
+    </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/.idea/libraries/bouncy_castle.xml b/.idea/libraries/bouncy_castle.xml
index 4e4673a..70ec93b 100644
--- a/.idea/libraries/bouncy_castle.xml
+++ b/.idea/libraries/bouncy_castle.xml
@@ -1,10 +1,13 @@
 <component name="libraryTable">
   <library name="bouncy-castle">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/android/android/lib/bcpkix-jdk15on-1.48.jar!/" />
-      <root url="jar://$PROJECT_DIR$/android/android/lib/bcprov-jdk15on-1.48.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48.jar!/" />
     </CLASSES>
     <JAVADOC />
-    <SOURCES />
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48-sources.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48-sources.jar!/" />
+    </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/.idea/libraries/builder_model.xml b/.idea/libraries/builder_model.xml
index e50dabd..c3378c2 100644
--- a/.idea/libraries/builder_model.xml
+++ b/.idea/libraries/builder_model.xml
@@ -1,11 +1,11 @@
 <component name="libraryTable">
   <library name="builder-model">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/android/android/lib/builder-model-0.12.0.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/builder-model/builder-model-0.13.0.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="jar://$PROJECT_DIR$/android/android/lib/src/builder-model-0.12.0-sources.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/builder-model/builder-model-0.13.0-sources.jar!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/.idea/libraries/commons_compress.xml b/.idea/libraries/commons_compress.xml
index a77ee36..be33df8 100644
--- a/.idea/libraries/commons_compress.xml
+++ b/.idea/libraries/commons_compress.xml
@@ -1,7 +1,7 @@
 <component name="libraryTable">
   <library name="commons-compress">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/android/android/lib/commons-compress-1.0.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/commons-compress/commons-compress-1.0.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES />
diff --git a/.idea/libraries/easymock_tools.xml b/.idea/libraries/easymock_tools.xml
index c996385..d01b884 100644
--- a/.idea/libraries/easymock_tools.xml
+++ b/.idea/libraries/easymock_tools.xml
@@ -1,10 +1,13 @@
 <component name="libraryTable">
   <library name="easymock-tools">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/lib/dev/easymockclassextension.jar!/" />
-      <root url="jar://$PROJECT_DIR$/lib/dev/easymock.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/easymock-tools/easymock-3.1.jar!/" />
     </CLASSES>
-    <JAVADOC />
-    <SOURCES />
+    <JAVADOC>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/easymock-tools/easymock-3.1-javadoc.jar!/" />
+    </JAVADOC>
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/easymock-tools/easymock-3.1-sources.jar!/" />
+    </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/.idea/libraries/fest.xml b/.idea/libraries/fest.xml
new file mode 100644
index 0000000..df47ca5
--- /dev/null
+++ b/.idea/libraries/fest.xml
@@ -0,0 +1,17 @@
+<component name="libraryTable">
+  <library name="fest">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-assert-1.2.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-reflect-1.2.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-swing-1.2.1.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-util-1.1.3.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-assert-1.2-sources.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-reflect-1.2-sources.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-swing-1.2.1-sources.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-util-1.1.3-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/freemarker_2_3_20.xml b/.idea/libraries/freemarker_2_3_20.xml
index 831297d..b7805a2 100644
--- a/.idea/libraries/freemarker_2_3_20.xml
+++ b/.idea/libraries/freemarker_2_3_20.xml
@@ -1,9 +1,11 @@
 <component name="libraryTable">
   <library name="freemarker-2.3.20">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/android/android/lib/freemarker-2.3.20.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/freemarker/freemarker/2.3.20/freemarker-2.3.20.jar!/" />
     </CLASSES>
     <JAVADOC />
-    <SOURCES />
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/freemarker/freemarker/2.3.20/freemarker-2.3.20-sources.jar!/" />
+    </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/.idea/libraries/google_api_java_client.xml b/.idea/libraries/google_api_java_client.xml
new file mode 100644
index 0000000..d76cd72
--- /dev/null
+++ b/.idea/libraries/google_api_java_client.xml
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+  <library name="google-api-java-client">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/google-api-java-client/1.8.0-rc/google-api-java-client-min-repackaged.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/junit3_tools.xml b/.idea/libraries/junit3_tools.xml
new file mode 100644
index 0000000..b3dd3f3
--- /dev/null
+++ b/.idea/libraries/junit3_tools.xml
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+  <library name="junit3-tools">
+    <CLASSES>
+      <root url="jar://$APPLICATION_HOME_DIR$/lib/junit.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/kxml2.xml b/.idea/libraries/kxml2.xml
index fe007f5..688c238 100644
--- a/.idea/libraries/kxml2.xml
+++ b/.idea/libraries/kxml2.xml
@@ -1,9 +1,13 @@
 <component name="libraryTable">
   <library name="kxml2">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/android/android/lib/kxml2-2.3.0.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/kxml2-tools/kxml2-2.3.0.jar!/" />
     </CLASSES>
-    <JAVADOC />
-    <SOURCES />
+    <JAVADOC>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/kxml2-tools/kxml2-src-2.3.0.zip!/www/kxml2/javadoc" />
+    </JAVADOC>
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/kxml2-tools/kxml2-src-2.3.0.zip!/src" />
+    </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/.idea/libraries/lombok_ast.xml b/.idea/libraries/lombok_ast.xml
index 9fe1aa4..ef9fe6d 100644
--- a/.idea/libraries/lombok_ast.xml
+++ b/.idea/libraries/lombok_ast.xml
@@ -1,16 +1,18 @@
 <component name="libraryTable">
   <library name="lombok-ast">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/android/android/lib/lombok-ast-0.2.2.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2.jar!/" />
     </CLASSES>
-    <JAVADOC />
+    <JAVADOC>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-javadoc.jar!/" />
+    </JAVADOC>
     <SOURCES>
-      <root url="jar://$PROJECT_DIR$/android/android/lib/src/lombok-ast-0.2.2-src.zip!/src/main" />
-      <root url="jar://$PROJECT_DIR$/android/android/lib/src/lombok-ast-0.2.2-src.zip!/src/printer" />
-      <root url="jar://$PROJECT_DIR$/android/android/lib/src/lombok-ast-0.2.2-src.zip!/src/template" />
-      <root url="jar://$PROJECT_DIR$/android/android/lib/src/lombok-ast-0.2.2-src.zip!/src/ecjTransformer" />
-      <root url="jar://$PROJECT_DIR$/android/android/lib/src/lombok-ast-0.2.2-src.zip!/src/javacTransformer" />
-      <root url="jar://$PROJECT_DIR$/android/android/lib/src/lombok-ast-0.2.2-src.zip!/build/lombok.ast_generatedSource" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/main" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/printer" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/template" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/ecjTransformer" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/javacTransformer" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/build/lombok.ast_generatedSource" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/.idea/libraries/mockito.xml b/.idea/libraries/mockito.xml
index a1ae9af..7113f6f 100644
--- a/.idea/libraries/mockito.xml
+++ b/.idea/libraries/mockito.xml
@@ -1,11 +1,12 @@
 <component name="libraryTable">
   <library name="mockito">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/android/android/lib/mockito-all-1.9.5.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/mockito/mockito-all/1.9.5/mockito-all-1.9.5.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="jar://$PROJECT_DIR$/android/android/lib/mockito-all-1.9.5.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/mockito/mockito-all/1.9.5/mockito-all-1.9.5-sources.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/mockito/mockito-all/1.9.5/mockito-all-1.9.5.jar!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 941f718..50ad2f0 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -5,6 +5,7 @@
   </component>
   <component name="FrameworkDetectionExcludesConfiguration">
     <file url="file://$PROJECT_DIR$" />
+    <type id="android" />
   </component>
   <component name="IdProvider" IDEtalkID="88DB5D232B345F18EEFB2825E88EC093" />
   <component name="JavadocGenerationManager">
@@ -24,6 +25,30 @@
     <option name="LOCALE" />
     <option name="OPEN_IN_BROWSER" value="true" />
   </component>
+  <component name="NullableNotNullManager">
+    <option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
+    <option name="myDefaultNotNull" value="org.jetbrains.annotations.NotNull" />
+    <option name="myNullables">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+          <item index="3" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
+        </list>
+      </value>
+    </option>
+    <option name="myNotNulls">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+          <item index="3" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
+        </list>
+      </value>
+    </option>
+  </component>
   <component name="ProjectDetails">
     <option name="projectName" value="idea-community" />
   </component>
diff --git a/.idea/modules.xml b/.idea/modules.xml
index f23cdde..62b77e8 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -10,26 +10,26 @@
       <module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-xml.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-xml.iml" group="plugins/IntelliLang" />
       <module fileurl="file://$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" filepath="$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/plugins/ShortcutPromoter/ShortcutPromoter.iml" filepath="$PROJECT_DIR$/plugins/ShortcutPromoter/ShortcutPromoter.iml" group="plugins" />
-      <module fileurl="file://$PROJECT_DIR$/android/adt-branding/adt-branding.iml" filepath="$PROJECT_DIR$/android/adt-branding/adt-branding.iml" group="android" />
+      <module fileurl="file://$PROJECT_DIR$/../adt/idea/adt-branding/adt-branding.iml" filepath="$PROJECT_DIR$/../adt/idea/adt-branding/adt-branding.iml" group="plugins/Android" />
       <module fileurl="file://$PROJECT_DIR$/platform/analysis-api/analysis-api.iml" filepath="$PROJECT_DIR$/platform/analysis-api/analysis-api.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/analysis-impl/analysis-impl.iml" filepath="$PROJECT_DIR$/platform/analysis-impl/analysis-impl.iml" group="platform" />
-      <module fileurl="file://$PROJECT_DIR$/android/android/android.iml" filepath="$PROJECT_DIR$/android/android/android.iml" group="android" />
-      <module fileurl="file://$PROJECT_DIR$/android/android/common/android-common.iml" filepath="$PROJECT_DIR$/android/android/common/android-common.iml" group="android" />
-      <module fileurl="file://$PROJECT_DIR$/android/android-gradle-jps/android-gradle-jps.iml" filepath="$PROJECT_DIR$/android/android-gradle-jps/android-gradle-jps.iml" group="android" />
-      <module fileurl="file://$PROJECT_DIR$/android/android/jps-plugin/android-jps-plugin.iml" filepath="$PROJECT_DIR$/android/android/jps-plugin/android-jps-plugin.iml" group="android" />
-      <module fileurl="file://$PROJECT_DIR$/android/android/rt/android-rt.iml" filepath="$PROJECT_DIR$/android/android/rt/android-rt.iml" group="android" />
+      <module fileurl="file://$PROJECT_DIR$/../adt/idea/android/android.iml" filepath="$PROJECT_DIR$/../adt/idea/android/android.iml" group="plugins/Android" />
+      <module fileurl="file://$PROJECT_DIR$/../adt/idea/android/common/android-common.iml" filepath="$PROJECT_DIR$/../adt/idea/android/common/android-common.iml" group="plugins/Android" />
+      <module fileurl="file://$PROJECT_DIR$/../adt/idea/android-gradle-jps/android-gradle-jps.iml" filepath="$PROJECT_DIR$/../adt/idea/android-gradle-jps/android-gradle-jps.iml" group="plugins/Android" />
+      <module fileurl="file://$PROJECT_DIR$/../adt/idea/android/jps-plugin/android-jps-plugin.iml" filepath="$PROJECT_DIR$/../adt/idea/android/jps-plugin/android-jps-plugin.iml" group="plugins/Android" />
+      <module fileurl="file://$PROJECT_DIR$/../adt/idea/android/rt/android-rt.iml" filepath="$PROJECT_DIR$/../adt/idea/android/rt/android-rt.iml" group="plugins/Android" />
       <module fileurl="file://$PROJECT_DIR$/platform/annotations/annotations.iml" filepath="$PROJECT_DIR$/platform/annotations/annotations.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/plugins/ant/ant.iml" filepath="$PROJECT_DIR$/plugins/ant/ant.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/ant/jps-plugin/ant-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/ant/jps-plugin/ant-jps-plugin.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/jps/antLayout/antlayout.iml" filepath="$PROJECT_DIR$/jps/antLayout/antlayout.iml" group="jps" />
       <module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/runtime/appEngine-runtime.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/runtime/appEngine-runtime.iml" group="plugins/GAE" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/asset-studio/assetstudio.iml" filepath="$PROJECT_DIR$/android/tools-base/asset-studio/assetstudio.iml" group="android/sdktools" />
+      <module fileurl="file://$PROJECT_DIR$/../base/asset-studio/assetstudio.iml" filepath="$PROJECT_DIR$/../base/asset-studio/assetstudio.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/platform/boot/boot.iml" filepath="$PROJECT_DIR$/platform/boot/boot.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" filepath="$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/build/build.iml" filepath="$PROJECT_DIR$/build/build.iml" />
       <module fileurl="file://$PROJECT_DIR$/colorSchemes/colorSchemes.iml" filepath="$PROJECT_DIR$/colorSchemes/colorSchemes.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/plugins/commander/commander.iml" filepath="$PROJECT_DIR$/plugins/commander/commander.iml" group="plugins" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/common/common.iml" filepath="$PROJECT_DIR$/android/tools-base/common/common.iml" group="android/sdktools" />
+      <module fileurl="file://$PROJECT_DIR$/../base/common/common.iml" filepath="$PROJECT_DIR$/../base/common/common.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/plugins/eclipse/common-eclipse-util/common-eclipse-util.iml" filepath="$PROJECT_DIR$/plugins/eclipse/common-eclipse-util/common-eclipse-util.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/javaFX/common-javaFX-plugin/common-javaFX-plugin.iml" filepath="$PROJECT_DIR$/plugins/javaFX/common-javaFX-plugin/common-javaFX-plugin.iml" group="plugins/JavaFX" />
       <module fileurl="file://$PROJECT_DIR$/community-main.iml" filepath="$PROJECT_DIR$/community-main.iml" />
@@ -47,7 +47,7 @@
       <module fileurl="file://$PROJECT_DIR$/build/cucumber-test-runner/cucumber-test-runner.iml" filepath="$PROJECT_DIR$/build/cucumber-test-runner/cucumber-test-runner.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/cvs/cvs-core/cvs-core.iml" filepath="$PROJECT_DIR$/plugins/cvs/cvs-core/cvs-core.iml" group="plugins/VCS/cvs" />
       <module fileurl="file://$PROJECT_DIR$/plugins/cvs/cvs-plugin/cvs-plugin.iml" filepath="$PROJECT_DIR$/plugins/cvs/cvs-plugin/cvs-plugin.iml" group="plugins/VCS/cvs" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/ddmlib/ddmlib.iml" filepath="$PROJECT_DIR$/android/tools-base/ddmlib/ddmlib.iml" group="android/sdktools" />
+      <module fileurl="file://$PROJECT_DIR$/../base/ddmlib/ddmlib.iml" filepath="$PROJECT_DIR$/../base/ddmlib/ddmlib.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/java/debugger/impl/debugger-impl.iml" filepath="$PROJECT_DIR$/java/debugger/impl/debugger-impl.iml" group="java" />
       <module fileurl="file://$PROJECT_DIR$/java/debugger/openapi/debugger-openapi.iml" filepath="$PROJECT_DIR$/java/debugger/openapi/debugger-openapi.iml" group="java" />
       <module fileurl="file://$PROJECT_DIR$/plugins/devkit/devkit.iml" filepath="$PROJECT_DIR$/plugins/devkit/devkit.iml" group="plugins" />
@@ -55,11 +55,11 @@
       <module fileurl="file://$PROJECT_DIR$/xml/dom-impl/dom-impl.iml" filepath="$PROJECT_DIR$/xml/dom-impl/dom-impl.iml" group="xml" />
       <module fileurl="file://$PROJECT_DIR$/xml/dom-openapi/dom-openapi.iml" filepath="$PROJECT_DIR$/xml/dom-openapi/dom-openapi.iml" group="xml" />
       <module fileurl="file://$PROJECT_DIR$/xml/dom-tests/dom-tests.iml" filepath="$PROJECT_DIR$/xml/dom-tests/dom-tests.iml" group="xml" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/draw9patch/draw9patch.iml" filepath="$PROJECT_DIR$/android/tools-base/draw9patch/draw9patch.iml" group="android/sdktools" />
+      <module fileurl="file://$PROJECT_DIR$/../base/draw9patch/draw9patch.iml" filepath="$PROJECT_DIR$/../base/draw9patch/draw9patch.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/platform/duplicates-analysis/duplicates-analysis.iml" filepath="$PROJECT_DIR$/platform/duplicates-analysis/duplicates-analysis.iml" />
       <module fileurl="file://$PROJECT_DIR$/platform/dvcs-api/dvcs-api.iml" filepath="$PROJECT_DIR$/platform/dvcs-api/dvcs-api.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/dvcs-impl/dvcs-impl.iml" filepath="$PROJECT_DIR$/platform/dvcs-impl/dvcs-impl.iml" group="platform" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/device_validator/dvlib/dvlib.iml" filepath="$PROJECT_DIR$/android/tools-base/device_validator/dvlib/dvlib.iml" group="android/sdktools" />
+      <module fileurl="file://$PROJECT_DIR$/../base/device_validator/dvlib/dvlib.iml" filepath="$PROJECT_DIR$/../base/device_validator/dvlib/dvlib.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/plugins/eclipse/eclipse.iml" filepath="$PROJECT_DIR$/plugins/eclipse/eclipse.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/eclipse/jps-plugin/eclipse-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/eclipse/jps-plugin/eclipse-jps-plugin.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" filepath="$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" group="platform" />
@@ -77,8 +77,9 @@
       <module fileurl="file://$PROJECT_DIR$/plugins/github/github.iml" filepath="$PROJECT_DIR$/plugins/github/github.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/google-app-engine.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/google-app-engine.iml" group="plugins/GAE" />
       <module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml" group="plugins/GAE" />
+      <module fileurl="file://$PROJECT_DIR$/../studio/cloud/google-cloud-tools.iml" filepath="$PROJECT_DIR$/../studio/cloud/google-cloud-tools.iml" group="plugins/Google" />
+      <module fileurl="file://$PROJECT_DIR$/../studio/cloud/login/google-login.iml" filepath="$PROJECT_DIR$/../studio/cloud/login/google-login.iml" group="plugins/Google" />
       <module fileurl="file://$PROJECT_DIR$/plugins/gradle/gradle.iml" filepath="$PROJECT_DIR$/plugins/gradle/gradle.iml" group="community/plugins/gradle" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/gradle-import/gradle-import.iml" filepath="$PROJECT_DIR$/android/tools-base/gradle-import/gradle-import.iml" group="android/sdktools" />
       <module fileurl="file://$PROJECT_DIR$/plugins/gradle/jps-plugin/gradle-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/gradle/jps-plugin/gradle-jps-plugin.iml" group="community/plugins/gradle" />
       <module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml" group="community/plugins/gradle" />
       <module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml" group="community/plugins/gradle" />
@@ -129,9 +130,9 @@
       <module fileurl="file://$PROJECT_DIR$/plugins/junit_rt/junit_rt.iml" filepath="$PROJECT_DIR$/plugins/junit_rt/junit_rt.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/platform/lang-api/lang-api.iml" filepath="$PROJECT_DIR$/platform/lang-api/lang-api.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/lang-impl/lang-impl.iml" filepath="$PROJECT_DIR$/platform/lang-impl/lang-impl.iml" group="platform" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/layoutlib-api/layoutlib-api.iml" filepath="$PROJECT_DIR$/android/tools-base/layoutlib-api/layoutlib-api.iml" group="android/sdktools" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/lint/libs/lint-api/lint-api.iml" filepath="$PROJECT_DIR$/android/tools-base/lint/libs/lint-api/lint-api.iml" group="android/sdktools" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/lint/libs/lint-checks/lint-checks.iml" filepath="$PROJECT_DIR$/android/tools-base/lint/libs/lint-checks/lint-checks.iml" group="android/sdktools" />
+      <module fileurl="file://$PROJECT_DIR$/../base/layoutlib-api/layoutlib-api.iml" filepath="$PROJECT_DIR$/../base/layoutlib-api/layoutlib-api.iml" group="plugins/Android/android-sdk" />
+      <module fileurl="file://$PROJECT_DIR$/../base/lint/libs/lint-api/lint-api.iml" filepath="$PROJECT_DIR$/../base/lint/libs/lint-api/lint-api.iml" group="plugins/Android/android-sdk/lint" />
+      <module fileurl="file://$PROJECT_DIR$/../base/lint/libs/lint-checks/lint-checks.iml" filepath="$PROJECT_DIR$/../base/lint/libs/lint-checks/lint-checks.iml" group="plugins/Android/android-sdk/lint" />
       <module fileurl="file://$PROJECT_DIR$/platform/lvcs-api/lvcs-api.iml" filepath="$PROJECT_DIR$/platform/lvcs-api/lvcs-api.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/lvcs-impl/lvcs-impl.iml" filepath="$PROJECT_DIR$/platform/lvcs-impl/lvcs-impl.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/android/android/main_AndroidStudio.iml" filepath="$PROJECT_DIR$/android/android/main_AndroidStudio.iml" group="android" />
@@ -139,7 +140,7 @@
       <module fileurl="file://$PROJECT_DIR$/python/main_pycharm_ce.iml" filepath="$PROJECT_DIR$/python/main_pycharm_ce.iml" group="python" />
       <module fileurl="file://$PROJECT_DIR$/python/edu/main_pycharm_edu.iml" filepath="$PROJECT_DIR$/python/edu/main_pycharm_edu.iml" group="python/educational" />
       <module fileurl="file://$PROJECT_DIR$/java/manifest/manifest.iml" filepath="$PROJECT_DIR$/java/manifest/manifest.iml" group="java" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/build-system/manifest-merger/manifest-merger.iml" filepath="$PROJECT_DIR$/android/tools-base/build-system/manifest-merger/manifest-merger.iml" group="android/sdktools" />
+      <module fileurl="file://$PROJECT_DIR$/../base/build-system/manifest-merger/manifest-merger.iml" filepath="$PROJECT_DIR$/../base/build-system/manifest-merger/manifest-merger.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/maven.iml" filepath="$PROJECT_DIR$/plugins/maven/maven.iml" group="plugins/maven" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/artifact-resolver-m2/maven-artifact-resolver-m2.iml" filepath="$PROJECT_DIR$/plugins/maven/artifact-resolver-m2/maven-artifact-resolver-m2.iml" group="plugins/maven" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/artifact-resolver-m3/maven-artifact-resolver-m3.iml" filepath="$PROJECT_DIR$/plugins/maven/artifact-resolver-m3/maven-artifact-resolver-m3.iml" group="plugins/maven" />
@@ -148,9 +149,9 @@
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/maven-server-api/maven-server-api.iml" filepath="$PROJECT_DIR$/plugins/maven/maven-server-api/maven-server-api.iml" group="plugins/maven" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/maven2-server-impl/maven2-server-impl.iml" filepath="$PROJECT_DIR$/plugins/maven/maven2-server-impl/maven2-server-impl.iml" group="plugins/maven" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/maven3-server-impl/maven3-server-impl.iml" filepath="$PROJECT_DIR$/plugins/maven/maven3-server-impl/maven3-server-impl.iml" group="plugins/maven" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/ninepatch/ninepatch.iml" filepath="$PROJECT_DIR$/android/tools-base/ninepatch/ninepatch.iml" group="android/sdktools" />
+      <module fileurl="file://$PROJECT_DIR$/../base/ninepatch/ninepatch.iml" filepath="$PROJECT_DIR$/../base/ninepatch/ninepatch.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/java/openapi/openapi.iml" filepath="$PROJECT_DIR$/java/openapi/openapi.iml" group="java" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/perflib/perflib.iml" filepath="$PROJECT_DIR$/android/tools-base/perflib/perflib.iml" group="android/sdktools" />
+      <module fileurl="file://$PROJECT_DIR$/../base/perflib/perflib.iml" filepath="$PROJECT_DIR$/../base/perflib/perflib.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/platform/platform-api/platform-api.iml" filepath="$PROJECT_DIR$/platform/platform-api/platform-api.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/platform-impl/platform-impl.iml" filepath="$PROJECT_DIR$/platform/platform-impl/platform-impl.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/platform-main/platform-main.iml" filepath="$PROJECT_DIR$/platform/platform-main/platform-main.iml" group="platform" />
@@ -188,8 +189,8 @@
       <module fileurl="file://$PROJECT_DIR$/python/rest/rest.iml" filepath="$PROJECT_DIR$/python/rest/rest.iml" group="python" />
       <module fileurl="file://$PROJECT_DIR$/platform/script-debugger/backend/script-debugger-backend.iml" filepath="$PROJECT_DIR$/platform/script-debugger/backend/script-debugger-backend.iml" group="platform/script-debugger" />
       <module fileurl="file://$PROJECT_DIR$/platform/script-debugger/debugger-ui/script-debugger-ui.iml" filepath="$PROJECT_DIR$/platform/script-debugger/debugger-ui/script-debugger-ui.iml" group="platform/script-debugger" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/sdk-common/sdk-common.iml" filepath="$PROJECT_DIR$/android/tools-base/sdk-common/sdk-common.iml" group="android/sdktools" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/sdklib/sdklib.iml" filepath="$PROJECT_DIR$/android/tools-base/sdklib/sdklib.iml" group="android/sdktools" />
+      <module fileurl="file://$PROJECT_DIR$/../base/sdk-common/sdk-common.iml" filepath="$PROJECT_DIR$/../base/sdk-common/sdk-common.iml" group="plugins/Android/android-sdk" />
+      <module fileurl="file://$PROJECT_DIR$/../base/sdklib/sdklib.iml" filepath="$PROJECT_DIR$/../base/sdklib/sdklib.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/platform/smRunner/smRunner.iml" filepath="$PROJECT_DIR$/platform/smRunner/smRunner.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/plugins/cvs/smartcvs-src/smartcvs-src.iml" filepath="$PROJECT_DIR$/plugins/cvs/smartcvs-src/smartcvs-src.iml" group="plugins/VCS/cvs" />
       <module fileurl="file://$PROJECT_DIR$/spellchecker/spellchecker.iml" filepath="$PROJECT_DIR$/spellchecker/spellchecker.iml" group="plugins" />
@@ -212,11 +213,12 @@
       <module fileurl="file://$PROJECT_DIR$/plugins/testng/testng.iml" filepath="$PROJECT_DIR$/plugins/testng/testng.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/testng_rt/testng_rt.iml" filepath="$PROJECT_DIR$/plugins/testng_rt/testng_rt.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/platform/testFramework/bootstrap/tests_bootstrap.iml" filepath="$PROJECT_DIR$/platform/testFramework/bootstrap/tests_bootstrap.iml" group="platform" />
-      <module fileurl="file://$PROJECT_DIR$/android/tools-base/testutils/testutils.iml" filepath="$PROJECT_DIR$/android/tools-base/testutils/testutils.iml" group="android/sdktools" />
+      <module fileurl="file://$PROJECT_DIR$/../base/testutils/testutils.iml" filepath="$PROJECT_DIR$/../base/testutils/testutils.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/java/typeMigration/typeMigration.iml" filepath="$PROJECT_DIR$/java/typeMigration/typeMigration.iml" />
       <module fileurl="file://$PROJECT_DIR$/plugins/ui-designer/ui-designer.iml" filepath="$PROJECT_DIR$/plugins/ui-designer/ui-designer.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/ui-designer-core/ui-designer-core.iml" filepath="$PROJECT_DIR$/plugins/ui-designer-core/ui-designer-core.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/ui-designer/jps-plugin/ui-designer-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/ui-designer/jps-plugin/ui-designer-jps-plugin.iml" group="plugins" />
+      <module fileurl="file://$PROJECT_DIR$/updater/updater.iml" filepath="$PROJECT_DIR$/updater/updater.iml" />
       <module fileurl="file://$PROJECT_DIR$/platform/usageView/usageView.iml" filepath="$PROJECT_DIR$/platform/usageView/usageView.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/util/util.iml" filepath="$PROJECT_DIR$/platform/util/util.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/util-rt/util-rt.iml" filepath="$PROJECT_DIR$/platform/util-rt/util-rt.iml" group="platform" />
diff --git a/.idea/runConfigurations/AndroidStudio.xml b/.idea/runConfigurations/AndroidStudio.xml
new file mode 100644
index 0000000..c62432d
--- /dev/null
+++ b/.idea/runConfigurations/AndroidStudio.xml
@@ -0,0 +1,25 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="AndroidStudio" type="Application" factoryName="Application" singleton="true">
+    <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+    <option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
+    <option name="VM_PARAMETERS" value="-ea -Xbootclasspath/p:../out/classes/production/boot -Xms384m -Xmx768m -Didea.is.internal=true -XX:MaxPermSize=384m -Dapple.awt.graphics.UseQuartz=true -Didea.platform.prefix=AndroidStudio -Dandroid.extra_templates.path=../../../sdk/templates -Dapple.laf.useScreenMenuBar=true -Dcom.apple.mrj.application.apple.menu.about.name=AndroidStudio -Dsun.awt.disablegrab=true" />
+    <option name="PROGRAM_PARAMETERS" value="" />
+    <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bin" />
+    <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+    <option name="ALTERNATIVE_JRE_PATH" value="" />
+    <option name="ENABLE_SWING_INSPECTOR" value="false" />
+    <option name="ENV_VARIABLES" />
+    <option name="PASS_PARENT_ENVS" value="true" />
+    <module name="community-main" />
+    <envs />
+    <RunnerSettings RunnerId="Debug">
+      <option name="DEBUG_PORT" value="" />
+      <option name="TRANSPORT" value="0" />
+      <option name="LOCAL" value="true" />
+    </RunnerSettings>
+    <RunnerSettings RunnerId="Run" />
+    <ConfigurationWrapper RunnerId="Debug" />
+    <ConfigurationWrapper RunnerId="Run" />
+    <method />
+  </configuration>
+</component>
\ No newline at end of file
diff --git a/.idea/scopes/androidplugin.xml b/.idea/scopes/androidplugin.xml
new file mode 100644
index 0000000..dcc1341
--- /dev/null
+++ b/.idea/scopes/androidplugin.xml
@@ -0,0 +1,3 @@
+<component name="DependencyValidationManager">
+  <scope name="androidplugin" pattern="file[group:Android]:*//*&amp;&amp;!file[group:android-sdk]:*//*" />
+</component>
\ No newline at end of file
diff --git a/.idea/scopes/aosp_code.xml b/.idea/scopes/aosp_code.xml
new file mode 100644
index 0000000..abf77af
--- /dev/null
+++ b/.idea/scopes/aosp_code.xml
@@ -0,0 +1,3 @@
+<component name="DependencyValidationManager">
+  <scope name="aosp-code" pattern="test[group:android-sdk]:*..*||src[group:android-sdk]:*..*" />
+</component>
\ No newline at end of file
diff --git a/.idea/scopes/obsoleteplugin.xml b/.idea/scopes/obsoleteplugin.xml
new file mode 100644
index 0000000..0537436
--- /dev/null
+++ b/.idea/scopes/obsoleteplugin.xml
@@ -0,0 +1,3 @@
+<component name="DependencyValidationManager">
+  <scope name="obsoleteplugin" pattern="file[community-main]:plugins/android//*||file[community-main]:plugins/android-designer//*" />
+</component>
\ No newline at end of file
diff --git a/.idea/scopes/platform.xml b/.idea/scopes/platform.xml
new file mode 100644
index 0000000..a0bafd1
--- /dev/null
+++ b/.idea/scopes/platform.xml
@@ -0,0 +1,3 @@
+<component name="DependencyValidationManager">
+  <scope name="platform" pattern="src:*..*&amp;&amp;!src[group:Android]:*..*" />
+</component>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index a1b9ce9..d10a1db 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,8 +2,9 @@
 <project version="4">
   <component name="VcsDirectoryMappings">
     <mapping directory="" vcs="Git" />
-    <mapping directory="$PROJECT_DIR$/android" vcs="Git" />
-    <mapping directory="$PROJECT_DIR$/android/tools-base" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/../adt/idea" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/../base" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/../studio/cloud" vcs="Git" />
   </component>
 </project>
 
diff --git a/build.xml b/build.xml
index 8e6bdbc..e651cf0 100644
--- a/build.xml
+++ b/build.xml
@@ -1,7 +1,23 @@
 <project name="IntelliJ IDEA Community Edition" default="all">
   <property name="project.home" value="${basedir}"/>
-  <property name="out.dir" value="${project.home}/out"/>
-  <property name="tmp.dir" value="${project.home}/out/tmp"/>
+
+  <!--
+    Sets the out folder. Defaults to ${basedir}/out.
+    To override, use command line arg "out": e.g. -Dout=/path/
+  -->
+  <condition property="out.dir" value="${out}" else="${project.home}/out">
+    <isset property="out" />
+  </condition>
+
+  <property name="tmp.dir" value="${out.dir}/tmp"/>
+
+  <!--
+    Sets the build number. Defaults to SNAPSHOT.
+    To override, use command line arg "buildNumber": e.g. -DbuildNumber=777
+  -->
+  <condition property="buildId" value="${buildNumber}" else="SNAPSHOT">
+    <isset property="buildNumber" />
+  </condition>
 
   <target name="cleanup">
     <delete dir="${out.dir}" failonerror="false"/>
@@ -14,12 +30,16 @@
 
   <macrodef name="call_gant">
     <attribute name="script" />
+    <attribute name="test.patterns" default="" />
     <sequential>
       <java failonerror="true" jar="${project.home}/lib/ant/lib/ant-launcher.jar" fork="true">
-        <jvmarg line="-Xmx612m -XX:MaxPermSize=152m"/>
+        <jvmarg line="-Xmx2048m -XX:MaxPermSize=512m"/>
+        <jvmarg value="-Dout=${out.dir}" />
+        <jvmarg value="-DbuildNumber=${buildId}" />
         <sysproperty key="java.awt.headless" value="true"/>
         <arg line="&quot;-Dgant.script=@{script}&quot;"/>
         <arg line="&quot;-Dteamcity.build.tempDir=${tmp.dir}&quot;"/>
+        <arg line="&quot;-Didea.test.patterns=@{test.patterns}&quot;"/>
         <arg line="&quot;-Didea.test.group=ALL_EXCLUDE_DEFINED&quot;"/>
         <arg value="-f"/>
         <arg value="${project.home}/build/gant.xml"/>
@@ -32,8 +52,24 @@
   </target>
 
   <target name="test" depends="init">
-    <call_gant script="${project.home}/build/scripts/tests.gant"/>
+    <call_gant script="${project.home}/build/scripts/tests.gant" test.patterns="org.jetbrains.android.*;com.android.tools.idea.*;com.google.gct.*"/>
   </target>
 
-  <target name="all" depends="cleanup,build"/>
+  <target name="guiTests" depends="init">
+    <delete>
+      <fileset dir="${project.home}/build" includes="TEST-com.android.tools.idea.tests.gui.*"/>
+    </delete>
+    <call_gant script="${project.home}/build/scripts/gui_tests.gant"/>
+  </target>
+
+  <!-- The build task creates an updater.jar in ${out.dir}. This task bundles log4j & the updater into a single jar -->
+  <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="${project.home}/build/lib/jarjar-1.0.jar"/>
+  <target name="fullupdater" depends="build">
+    <jarjar jarfile="${out.dir}/updater-full.jar">
+        <zipfileset src="${out.dir}/updater.jar" />
+        <zipfileset src="lib/log4j.jar" />
+    </jarjar>
+  </target>
+
+  <target name="all" depends="cleanup,build,fullupdater"/>
 </project>
diff --git a/build/Install-Linux-tar.txt b/build/Install-Linux-tar.txt
index 8c9f048..2faac26 100644
--- a/build/Install-Linux-tar.txt
+++ b/build/Install-Linux-tar.txt
@@ -11,7 +11,7 @@
 
   2. Open a console and cd into "{installation home}/bin" and type:
 
-       ./@@product@@.sh
+       ./@@script_name@@
 
      to start the application.
 
diff --git a/build/conf/mac/Contents/Info.plist b/build/conf/mac/Contents/Info.plist
index 3f26292..c4ac45b 100644
--- a/build/conf/mac/Contents/Info.plist
+++ b/build/conf/mac/Contents/Info.plist
@@ -39,11 +39,11 @@
     <key>CFBundleSignature</key>
     <string>????</string>
     <key>CFBundleGetInfoString</key>
-    <string>@@bundle_name@@ @@version@@, build @@build@@. Copyright JetBrains s.r.o., (c) 2000-@@year@@</string>
+    <string>@@bundle_name@@ EAP, build EAP. Copyright @@company_name@@, (c) @@min_year@@-@@max_year@@</string>
     <key>CFBundleShortVersionString</key>
-    <string>@@version@@</string>
+    <string>EAP</string>
     <key>CFBundleVersion</key>
-    <string>@@build@@</string>
+    <string>EAP</string>
     <key>LSApplicationCategoryType</key>
     <string>public.app-category.developer-tools</string>
     <key>CFBundleHelpBookName</key>
diff --git a/build/gant.xml b/build/gant.xml
index 4b56378..7991950a 100644
--- a/build/gant.xml
+++ b/build/gant.xml
@@ -47,6 +47,9 @@
   </taskdef>
 
   <target name="doGant">
-    <gant file="${gant.script}" target="${gant.target}"/>
+    <gant file="${gant.script}" target="${gant.target}">
+      <definition name="teamcity.build.tempDir" value="${teamcity.build.tempDir}"/>
+      <definition name="idea.test.patterns" value="${idea.test.patterns}"/>
+    </gant>
   </target>
 </project>
diff --git a/build/scripts/common_tests.gant b/build/scripts/common_tests.gant
index d9e4138..eb21bac 100644
--- a/build/scripts/common_tests.gant
+++ b/build/scripts/common_tests.gant
@@ -20,6 +20,10 @@
 
 requireProperty("out", "$home/out")
 
+target(check: "Ensure the environment is configured") {
+  tempDir = p("teamcity.build.tempDir")
+}
+
 target(compile: "Compile project") {
   ant.delete(failonerror: false) {
     fileset(dir: "$home/reports")
@@ -39,7 +43,7 @@
 }
 
 target('run_tests': 'Run java tests') {
-  depends([compile])
+  depends([check, compile])
 
   def classpathFile = "$home/junit.classpath"
   List<String> testRuntimeClasspath = projectBuilder.moduleRuntimeClasspath(findModule("community-main"), true)
@@ -84,5 +88,5 @@
 }
 
 target('default' : "Run all tests") {
-  depends([compile, run_tests, run_cucumber_tests])
-}
\ No newline at end of file
+  depends([compile, run_tests])
+}
diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant
index a79fb54..81400fb 100644
--- a/build/scripts/dist.gant
+++ b/build/scripts/dist.gant
@@ -19,6 +19,12 @@
 includeTargets << new File("${guessHome(this)}/build/scripts/utils.gant")
 
 requireProperty("out", "$home/out")
+requireProperty("buildNumber", "SNAPSHOT")
+
+// "out" has to be canonical, otherwise the ant build fails
+// with mysterious errors
+out = new File(out).getCanonicalPath()
+setProperty("out", out)
 
 class Paths {
   final sandbox
@@ -62,7 +68,7 @@
 }
 
 private String appInfoFile() {
-  return "${projectBuilder.moduleOutput(findModule("community-resources"))}/idea/IdeaApplicationInfo.xml"
+  return "${projectBuilder.moduleOutput(findModule("adt-branding"))}/idea/AndroidStudioApplicationInfo.xml"
 }
 
 target('default': 'The default target') {
@@ -73,10 +79,17 @@
 
   zipSources(home, paths.artifacts)
 
-  layoutAll([buildNumber: "IC-$snapshot",
-             system_selector: "IdeaIC${p("component.version.major")}",
+  layoutAll([buildNumber: "AI-$snapshot".replaceAll("SNAPSHOT", p("buildNumber")),
+             system_selector: "AndroidStudioPreview",
+             platform_prefix: "AndroidStudio",
+             icns: "${projectBuilder.moduleOutput(findModule("adt-branding"))}/artwork/AndroidStudio.icns",
+             ide_jvm_args: "-Didea.platform.prefix=AndroidStudio",
              tools_jar: true],
             home, null, paths, true)
+
+  // Generate updater.jar from the updater module (patch updater)
+  projectBuilder.stage("Generating updater in $out")
+  layoutUpdater(out)
 }
 
 target('build-dist-jars' : 'Target to build jars from locally compiled classes') {
@@ -84,7 +97,7 @@
   // load ApplicationInfo.xml properties
   ant.xmlproperty(file: appInfoFile(), collapseAttributes: "true")
 
-  layoutAll([buildNumber: "IC-$snapshot",
+  layoutAll([buildNumber: "AI-$snapshot".replaceAll("SNAPSHOT", p("buildNumber")),
              system_selector: "IdeaIC${p("component.version.major")}",
              tools_jar: true],
              home, null, paths)
@@ -93,6 +106,8 @@
 def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = false) {
   Paths paths = _paths != null ? _paths : new Paths(out)
 
+  args.companyName = p("component.company.name")
+
   wireBuildDate(args.buildNumber, appInfoFile())
   ant.echo(message: args.buildNumber, file: "$paths.distAll/build.txt")
 
@@ -123,44 +138,63 @@
   layoutMac(args, home, paths)
   layoutUnix(args, home, paths)
 
-  buildWinZip("$paths.artifacts/idea${args.buildNumber}.win.zip", [paths.distAll, paths.distWin])
+  def winAppRoot = "android-studio"
+  def macAppRoot = "Android Studio.app/Contents"
+  def linTarRoot = "android-studio"
 
-  def macAppRoot = isEap() ?
-                   "IntelliJ IDEA ${p("component.version.major")} CE EAP.app/Contents" :
-                   "IntelliJ IDEA ${p("component.version.major")} CE.app/Contents"
+  androidBuildNumber = p("buildNumber")
+  //def macAppRoot = isEap() ?
+  //                 "IntelliJ IDEA ${p("component.version.major")} CE EAP.app/Contents" :
+  //                 "IntelliJ IDEA ${p("component.version.major")} CE.app/Contents"
 
-  String macZip = "$paths.artifacts/idea${args.buildNumber}.mac.zip"
+  def winZip = "$paths.artifacts/android-studio-${androidBuildNumber}.win.zip"
+  def macZip = "$paths.artifacts/android-studio-${androidBuildNumber}.mac.zip"
+  def linTar = "$paths.artifacts/android-studio-${androidBuildNumber}.tar"
+
+  buildWinZip(winAppRoot, winZip, [paths.distAll, paths.distWin])
+  buildTarGz(linTarRoot, linTar, [paths.distAll, paths.distUnix])
   buildMacZip(macAppRoot, macZip, [paths.distAll], paths.distMac)
-  notifyArtifactBuilt(macZip)
-
-  buildTarGz("idea-${args.buildNumber}", "$paths.artifacts/idea${args.buildNumber}.tar", [paths.distAll, paths.distUnix])
 }
 
-private layoutWin(Map args, String home, Paths paths) {
+private layoutWin(Map _args, String home, Paths paths) {
   String target = paths.distWin
 
+  Map args = new HashMap(_args)
+  args.product_uc = "ANDROID_STUDIO"
+  args.vm_options = "studio.exe"
+
   layout(target) {
     dir("bin") {
       fileset(dir: "$home/bin/win")
     }
   }
 
-  ant.copy(file: "$home/platform/icons/src/idea_CE.ico", tofile: "$target/bin/idea.ico")
+  ant.copy(file: "$home/../adt/idea/adt-branding/src/artwork/androidstudio.ico", tofile: "$target/bin/idea.ico")
 
-  winScripts(target, home, "idea.bat", args)
-  winVMOptions(target, null, "idea.exe", "idea64.exe")
-  List resourcePaths = ["$home/community-resources/src", "$home/platform/icons/src"]
-  buildWinLauncher(home, "$home/bin/WinLauncher/WinLauncher.exe", "$target/bin/idea.exe", appInfoFile(),
-                   "$home/build/conf/ideaCE-launcher.properties", args.ce_exe_selector, resourcePaths)
-  buildWinLauncher(home, "$home/bin/WinLauncher/WinLauncher64.exe", "$target/bin/idea64.exe", appInfoFile(),
-                   "$home/build/conf/ideaCE64-launcher.properties", args.ce_exe_selector, resourcePaths)
+  // The 0.1.1 win launcher.
+  ant.copy(  file: "$home/../adt/idea/native/WinLauncher/out/Release-Win32/studio.exe",
+           tofile: "$target/bin/studio.exe")
+  ant.copy(  file: "$home/../adt/idea/native/WinLauncher/out/Release-Win32/studio.exe.manifest",
+           tofile: "$target/bin/studio.exe.manifest")
+  ant.copy(  file: "$home/../adt/idea/native/WinLauncher/out/Release-x64/studio64.exe",
+           tofile: "$target/bin/studio64.exe")
+  ant.copy(  file: "$home/../adt/idea/native/WinLauncher/out/Release-x64/studio64.exe.manifest",
+           tofile: "$target/bin/studio64.exe.manifest")
+  // Manual updater script
+  ant.copy(  file: "$home/../adt/idea/native/update_studio.bat",
+           tofile: "$target/bin/update_studio.bat")
+
+  winScripts(target, home, "studio.bat", args)
+  winVMOptions(target, args, "studio.exe", "studio64.exe")
 }
 
 private layoutMac(Map _args, String home, Paths paths) {
   String target = paths.distMac
 
   Map args = new HashMap(_args)
-  args.bundleIdentifier = "com.jetbrains.intellij.ce"
+  args.bundleIdentifier = "com.google.android.studio"
+  args.executable = "studio"
+  args.help_id = "AI"
   args.doc_types = """
       <dict>
         <key>CFBundleTypeExtensions</key>
@@ -178,21 +212,34 @@
   args."idea.properties.path" = "${paths.distAll}/bin/idea.properties"
   args.urlSchemes = ["idea"]
   args.mac_no_yjp = true
+
+  // Manual updater script
+  ant.copy(file: "$home/../adt/idea/native/update_studio.sh", tofile: "$target/bin/update_studio.sh")
+
   layoutMacApp(target, home, args)
 }
 
-private layoutUnix(Map args, String home, Paths paths) {
+private layoutUnix(Map _args, String home, Paths paths) {
   String target = paths.distUnix
 
+  Map args = new HashMap(_args)
+  args.product_uc = "STUDIO"
+  args.vm_options = "studio"
+  args.script_name = "studio.sh"
+
   layout(target) {
     dir("bin") {
       fileset(dir: "$home/bin/linux")
     }
   }
 
-  ant.copy(file: "$home/platform/icons/src/icon_CE_128.png", tofile: "$target/bin/idea.png")
+  ant.copy(file: "$home/../adt/idea/adt-branding/src/artwork/icon_AS_128.png", tofile: "$target/bin/idea.png")
+  ant.copy(file: "$home/../adt/idea/adt-branding/src/artwork/androidstudio.ico", tofile: "$target/bin/androidstudio.ico")
 
-  unixScripts(target, home, "idea.sh", args)
-  unixVMOptions(target, "idea")
+  // Manual updater script
+  ant.copy(file: "$home/../adt/idea/native/update_studio.sh", tofile: "$target/bin/update_studio.sh")
+
+  unixScripts(target, home, args.script_name, args)
+  unixVMOptions(target, "studio")
   unixReadme(target, home, args)
 }
diff --git a/build/scripts/gui_tests.gant b/build/scripts/gui_tests.gant
new file mode 100644
index 0000000..00061c7
--- /dev/null
+++ b/build/scripts/gui_tests.gant
@@ -0,0 +1,88 @@
+// Based on tests.gant but with the includeTargets of common_tests inlined
+// below (and with some changes to invoke our GUI test suite instead
+import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome
+
+includeTargets << new File("${guessHome(this)}/build/scripts/utils.gant")
+
+requireProperty("out", "$home/out")
+
+target(check: "Ensure the environment is configured") {
+  tempDir = p("teamcity.build.tempDir")
+}
+
+target(compile: "Compile project") {
+  ant.delete(failonerror: false) {
+    fileset(dir: "$home/reports")
+    fileset(dir: "$home/bin", includes: "*.hprof")
+  }
+
+  loadProject()
+  projectBuilder.targetFolder = out
+  if (!isDefined("skip_build")) {
+    projectBuilder.cleanOutput()
+    projectBuilder.buildAll()
+  }
+}
+
+private pass(String prop) {
+  if (isDefined(prop)) {
+    ant.jvmarg(value: "-D$prop=${p(prop)}")
+  }
+}
+
+target('run_ui_tests': 'Run java tests') {
+  depends([check, compile])
+
+  ant.junit(fork: "yes", showoutput: "true", logfailedtests:false, printsummary: "true") {
+    pass("idea.test.group")
+    pass("idea.test.patterns")
+    pass("idea.fast.only")
+    pass("teamcity.build.tempDir")
+    pass("teamcity.tests.recentlyFailedTests.file")
+
+    System.getProperties().entrySet().each {
+      if (it.key.startsWith("pass.")) {
+        def trimmed = it.key.substring("pass.".length());
+        jvmarg(value: "-D${trimmed}=${it.value}");
+      };
+    }
+
+    commonJvmArgs().each { jvmarg(value: it) }
+
+    if (isDefined("jvm_args")) {
+      jvm_args.each { jvmarg(value: it) }
+    }
+
+    classpath {
+      projectBuilder.moduleRuntimeClasspath(findModule("community-main"), true).each {
+        pathelement(location: it)
+      }
+      pathelement(location: "${jdkHome}/lib/tools.jar")
+    }
+
+    formatter(type: "plain")
+    formatter(type: "xml")
+
+    testcases.each {
+      test (name: it)
+    }
+  }
+}
+
+target('default' : "Run all UI tests") {
+  depends([compile, run_ui_tests])
+  depends([run_ui_tests])
+}
+
+// To run just your own tests, you can for example write
+//setProperty("testcases", ["com.android.tools.idea.tests.gui.layout.LayoutPreviewTest","com.android.tools.idea.tests.gui.layout.LayoutEditorTest"])
+setProperty("testcases", ["com.android.tools.idea.tests.gui.GuiTestSuite"])
+
+def args = [
+        "-Xmx2048m",
+        "-XX:MaxPermSize=1024m",
+        "-XX:ReservedCodeCacheSize=96m",
+        "-XX:+UseCodeCacheFlushing"
+]
+
+setProperty("jvm_args", args)
diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant
index 6eb85a7..69c817e 100644
--- a/build/scripts/layouts.gant
+++ b/build/scripts/layouts.gant
@@ -13,6 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+import org.jetbrains.jps.model.java.JpsJavaClasspathKind
+import org.jetbrains.jps.model.module.JpsLibraryDependency
+import org.jetbrains.jps.model.library.JpsOrderRootType
+import org.jetbrains.jps.util.JpsPathUtil
+
 import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome
 
 includeTargets << new File("${guessHome(this)}/build/scripts/utils.gant")
@@ -24,7 +30,7 @@
 }
 
 String appInfoFileName() {
-  return "idea/IdeaApplicationInfo.xml"
+  return "idea/AndroidStudioApplicationInfo.xml"
 }
 
 String patchAppDescriptor(String targetDirectory) {
@@ -33,12 +39,12 @@
   ant.delete(dir: patchedDirectory)
 
   layout(patchedDirectory) {
-    module("community-resources") {
+    module("adt-branding") {
       include(name: appInfoFileName())
     }
   }
 
-  ant.replace(file: "$patchedDirectory/${appInfoFileName()}", token: "__BUILD_NUMBER__", value: "IC-$snapshot")
+  ant.replace(file: "$patchedDirectory/${appInfoFileName()}", token: "__BUILD_NUMBER__", value: "AI-$snapshot")
   ant.replace(file: "$patchedDirectory/${appInfoFileName()}", token: "__BUILD_DATE__", value: new Date().format("yyyyMMddHHmm"))
 
   return patchedDirectory
@@ -152,7 +158,8 @@
         module("colorSchemes")
         module("resources")
         module("platform-resources")
-        module("community-resources") {
+        module("community-resources")
+        module("adt-branding") {
           if (patchedDescriptorDir != null) {
             exclude(name: appInfoFileName())
           }
@@ -254,7 +261,8 @@
 }
 
 public def layoutCommunityPlugins(String home) {
-  layoutAndroid("$home/android")
+  layoutAndroid()
+  layoutGoogle()
 
   dir("plugins") {
     def simplePlugins = ["commander", "copyright", "java-i18n", "hg4idea", "github"] //, "tasks-time-tracking"]
@@ -263,18 +271,21 @@
       layoutPlugin it
     }
 
-    layoutPlugin("ant", "ant", "antIntegration") {
-      jar("ant-jps-plugin.jar") {
-        module("ant-jps-plugin")
-      }
-    }
-    layoutPlugin("uiDesigner", "ui-designer", "uiDesigner") {
-      dir("jps") {
-        jar("ui-designer-jps-plugin.jar") {
-          module("ui-designer-jps-plugin")
-        }
-      }
-    }
+    // ant not needed in AS
+    // layoutPlugin("ant", "ant", "antIntegration") {
+    //   jar("ant-jps-plugin.jar") {
+    //     module("ant-jps-plugin")
+    //   }
+    // }
+
+    // uiDesigner not needed in AS
+    // layoutPlugin("uiDesigner", "ui-designer", "uiDesigner") {
+    //   dir("jps") {
+    //     jar("ui-designer-jps-plugin.jar") {
+    //       module("ui-designer-jps-plugin")
+    //     }
+    //   }
+    // }
 
     pluginDir("properties") {
       dir("lib") {
@@ -381,13 +392,14 @@
       }
     }
 
-    pluginDir("ByteCodeViewer") {
-      dir("lib") {
-        jar("byteCodeViewer.jar") {
-          noResources("ByteCodeViewer")
-        }
-      }
-    }
+    // ByteCodeViewer not needed in AS
+    // pluginDir("ByteCodeViewer") {
+    //   dir("lib") {
+    //     jar("byteCodeViewer.jar") {
+    //       noResources("ByteCodeViewer")
+    //     }
+    //   }
+    // }
 
     pluginDir("cvsIntegration") {
       dir("lib") {
@@ -417,36 +429,38 @@
       }
     }
 
-    layoutPlugin("xpath") {
-      dir("rt") {
-        jar("xslt-rt.jar") {module("xslt-rt")}
-      }
-    }
+    // xpath not needed in AS
+    // layoutPlugin("xpath") {
+    //   dir("rt") {
+    //     jar("xslt-rt.jar") {module("xslt-rt")}
+    //   }
+    // }
 
-    layoutPlugin("xslt-debugger") {
-      jar("xslt-debugger-engine.jar") {
-        module("xslt-debugger-engine") {
-          excludes: "lib"
-        }
-      }
-      fileset(dir: "$home/plugins/xslt-debugger/engine/lib") {
-        include(name: "**/rmi-stubs.jar")
-      }
-      dir("rt") {
-        jar("xslt-debugger-engine-impl.jar") {
-          module("xslt-debugger-engine-impl") {
-            exclude(name: "lib")
-            exclude(name: "**/*.jar")
-            exclude(name: "**/*.html")
-          }
-        }
-        fileset(dir: "$home/plugins/xslt-debugger/engine/impl/lib") {
-          include(name: "**/*.jar")
-          exclude(name: "**/rmi-stubs.jar")
-          include(name: "**/*.html")
-        }
-      }
-    }
+    // xslt-debugger not needed in AS
+    // layoutPlugin("xslt-debugger") {
+    //   jar("xslt-debugger-engine.jar") {
+    //     module("xslt-debugger-engine") {
+    //       excludes: "lib"
+    //     }
+    //   }
+    //   fileset(dir: "$home/plugins/xslt-debugger/engine/lib") {
+    //     include(name: "**/rmi-stubs.jar")
+    //   }
+    //   dir("rt") {
+    //     jar("xslt-debugger-engine-impl.jar") {
+    //       module("xslt-debugger-engine-impl") {
+    //         exclude(name: "lib")
+    //         exclude(name: "**/*.jar")
+    //         exclude(name: "**/*.html")
+    //       }
+    //     }
+    //     fileset(dir: "$home/plugins/xslt-debugger/engine/impl/lib") {
+    //       include(name: "**/*.jar")
+    //       exclude(name: "**/rmi-stubs.jar")
+    //       include(name: "**/*.html")
+    //     }
+    //   }
+    // }
 
     pluginDir("Groovy") {
       dir("lib") {
@@ -493,22 +507,25 @@
       }
     }
 
-    layoutPlugin("devkit") {
-      jar("devkit-jps-plugin.jar") {
-        module("devkit-jps-plugin")
-      }
-      fileset(dir: "${home}/plugins/devkit/lib") {
-        include(name: "**/*.jar")
-      }
-    }
-    layoutPlugin("eclipse") {
-      jar("eclipse-jps-plugin.jar") {
-        module("eclipse-jps-plugin")
-      }
-      jar("common-eclipse-util.jar") {
-        module("common-eclipse-util")
-      }
-    }
+    // devkit not needed in AS
+    // layoutPlugin("devkit") {
+    //   jar("devkit-jps-plugin.jar") {
+    //     module("devkit-jps-plugin")
+    //   }
+    //   fileset(dir: "${home}/plugins/devkit/lib") {
+    //     include(name: "**/*.jar")
+    //   }
+    // }
+
+    // eclipse not needed in AS
+    // layoutPlugin("eclipse") {
+    //   jar("eclipse-jps-plugin.jar") {
+    //     module("eclipse-jps-plugin")
+    //   }
+    //   jar("common-eclipse-util.jar") {
+    //     module("common-eclipse-util")
+    //   }
+    // }
 
     layoutPlugin("terminal") {
       fileset(dir: "$home/plugins/terminal/lib") {
@@ -556,6 +573,85 @@
   }
 }
 
+def layoutGoogle() {
+  dir("plugins") {
+    layoutPlugin("google-cloud-tools") {
+      jar("google-cloud-tools.jar") {
+        module("google-cloud-tools")
+      }
+      dir("templates") {
+        fileset(dir: "${home}/../studio/cloud/resources/templates")
+      }
+      dir("clientTemplates") {
+        fileset(dir: "${home}/../studio/cloud/resources/clientTemplates")
+      }
+      fileset(dir: "${home}/../studio/cloud/lib") {
+        include(name: "**/*.jar")
+      }
+    }
+    layoutPlugin("google-login") {
+      jar("google-login.jar") {
+        module("google-login")
+      }
+      fileset(dir: "${home}/../studio/cloud/login/lib") {
+        include(name: "**/*.jar")
+      }
+      // Additional libraries that need to be manually copied, see how freemarker
+      // is copied by the Android plugin
+      fileset(file: "${home}/../../prebuilts/tools/common/google-api-java-client/1.8.0-rc/google-api-java-client-min-repackaged.jar")
+    }
+  }
+}
+
+private Set<String> findModuleDependencies(List<String> modules) {
+  Set<String> paths = new HashSet<String>();
+  modules.each {
+    m = findModule(it)
+    m.getDependenciesList().getDependencies().each {
+      projectBuilder.stage("looking at dependency " + it);
+
+      if (it instanceof JpsLibraryDependency) {  // only want library dependencies (and not other modules)
+        lib = it.getLibrary()
+        if (lib != null) {
+          libroots = lib.getRoots(JpsOrderRootType.COMPILED) // only want compile (and not test)
+          libroots.each {
+            paths.addAll(JpsPathUtil.urlToFile(it.getUrl()).getAbsolutePath());
+            projectBuilder.stage("Module: " + m.getName() + ", Dependency: " + it.getUrl());
+          }
+        }
+      }
+    }
+  }
+  return paths;
+}
+
+// Obtain the absolute path to the NOTICE file corresponding to the given jar file.
+// The NOTICE file is assumed to be present in the same folder as the jar file. It is an error if it is missing
+private File getNoticeFileForJar(String jarPath) {
+  File parentFile = new File(jarPath).getParentFile()
+  File notice = new File(parentFile, "NOTICE")
+  if (!notice.exists()) {
+    notice = new File(parentFile, "NOTICE.txt")
+  }
+  if (!notice.exists()) {
+    notice = new File(parentFile, "LICENSE.txt")
+  }
+  if (!notice.exists()) {
+    notice = new File(parentFile, "LICENSE")
+  }
+
+  return notice
+}
+
+private void appendToFile(File to, File from) {
+  if (from.exists()) {
+    to.append(from.getName() + ":\n")
+    to.append(from.getText("UTF-8"), "UTF-8")
+    projectBuilder.stage("Appending NOTICE file: " + from.getAbsolutePath())
+  } else {
+    projectBuilder.stage("Skipping non-existent NOTICE file: " + from.getAbsolutePath())
+  }
+}
 
 def layoutPlugin(String moduleName) {
   layoutPlugin(moduleName, moduleName, {})
@@ -661,61 +757,106 @@
   }
 }
 
-def layoutAndroid(String androidHome) {
+def layoutAndroid() {
   dir("plugins") {
-    layoutPlugin("android") {
-      fileset(dir: "${androidHome}/android/lib") {
-        include(name: "**/*.jar")
-        exclude(name: "**/ddmlib_1.jar")
-        exclude(name: "src/*.jar")
-      }
+    def androidModule = "android"
+    dir(androidModule) {
+      dir("lib") {
+        jar("android.jar") {
+          module("ui-designer-core") {
+            patternset(refid: "resources.excluded")
+          }
+          noResources(androidModule)
+        }
 
-      jar("android-common.jar") {
-        module("android-common")
-      }
+        jar("resources_en.jar") {
+          module(androidModule) {
+            patternset(refid: "resources.included")
+          }
+          module("ui-designer-core") {
+            patternset(refid: "resources.included")
+          }
+        }
 
-      jar("android-rt.jar") {
-        module("android-rt")
-      }
+        fileset(dir: "${home}/../adt/idea/android/lib") {
+          include(name: "**/*.jar")
+        }
 
-      jar("common.jar") {
-        module("common")
-      }
-      jar("sdklib.jar") {
-        module("sdklib")
-      }
-      jar("layoutlib-api.jar") {
-        module("layoutlib-api")
-      }
-      jar("manifest-merger.jar") {
-        module("manifest-merger")
-      }
-      jar("sdk-tools.jar") {
-        module("assetstudio")
-        module("ddmlib")
-        module("dvlib")
-        module("draw9patch")
-        module("lint-api")
-        module("lint-checks")
-        module("ninepatch")
-        module("sdk-common")
-        module("perflib")
-      }
-      jar("androidAnnotations.jar") {
-        fileset(dir: "$androidHome/android/annotations")
-      }
-      dir("jps") {
-        jar("android-gradle-jps.jar") { module("android-gradle-jps") }
-      }
-      dir("device-art-resources") {
-        fileset(dir: "$androidHome/android/device-art-resources")
-      }
+        jar("androidAnnotations.jar") {
+          fileset(dir: "${home}/../adt/idea/android/annotations")
+        }
 
-      dir("jps") {
-        jar("android-jps-plugin.jar") { module("android-jps-plugin") }
-      }
-      dir("templates") {
-        fileset(dir: "$androidHome/tools-base/templates")
+        // Add Additional libraries that the Android plugin depends on that come from TOOLS_PREBUILTS.
+        // Note: This is a HACK: rather than encoding the full path, we should really query
+        // the project model for the classpath just like we do for the androidModules' dependencies
+        // below
+        // Also see similar issue in Google Cloud Login plugin
+        fileset(file: "${home}/../../prebuilts/tools/common/m2/repository/org/freemarker/freemarker/2.3.20/freemarker-2.3.20.jar")
+
+        androidModules = [
+                "assetstudio",
+                "common",
+                "ddmlib",
+                "draw9patch",
+                "dvlib",
+                "layoutlib-api",
+                "lint-api",
+                "lint-checks",
+                "manifest-merger",
+                "ninepatch",
+                "perflib",
+                "sdk-common",
+                "sdklib"
+        ]
+
+        androidModules.each { moduleName ->
+          jar("${moduleName}.jar") {
+            module(moduleName)
+          }
+        }
+
+        // copy over dependencies of all android modules
+        androidModuleDeps = findModuleDependencies(androidModules)
+        androidModuleDeps.each {
+          fileset(file: it)
+        }
+
+        // Create a single NOTICE file with the contents of all the NOTICES of the dependencies.
+        // I couldn't figure out the right ant commands to be able to change the name of the file
+        // when copying, so we'll just call it by its final name (NOTICE)
+        File noticeFile = new File(System.getProperty("java.io.tmpdir") + File.separator + "NOTICE")
+        noticeFile.deleteOnExit()
+        androidModuleDeps.each {
+          appendToFile(noticeFile, getNoticeFileForJar(it))
+        }
+        appendToFile(noticeFile, new File("${home}/../../prebuilts/tools/common/m2/repository/org/freemarker/freemarker/2.3.20/NOTICE"))
+        fileset(file: noticeFile.getPath())
+
+        jar("android-common.jar") {
+          module("android-common")
+        }
+
+        jar("android-rt.jar") {
+          module("android-rt")
+        }
+
+        dir("jps") {
+          jar("android-jps-plugin.jar") { module("android-jps-plugin") }
+          jar("android-gradle-jps.jar") { module("android-gradle-jps") }
+        }
+
+        dir("device-art-resources") {
+          fileset(dir: "${home}/../adt/idea/android/device-art-resources")
+        }
+
+        dir("templates") {
+          fileset(dir: "${home}/../base/templates") {
+            include(name: "activities/**")
+            include(name: "gradle/**")
+            include(name: "other/**")
+            include(name: "gradle-projects/**")
+          }
+        }
       }
     }
   }
diff --git a/build/scripts/tests.gant b/build/scripts/tests.gant
index b512a18..03b740c 100644
--- a/build/scripts/tests.gant
+++ b/build/scripts/tests.gant
@@ -7,8 +7,8 @@
 
 def isMac = System.getProperty("os.name").toLowerCase().startsWith("mac")
 def args = [
-        "-Xmx450m",
-        "-XX:MaxPermSize=430m",
+        "-Xmx1024m",
+        "-XX:MaxPermSize=630m",
         "-XX:ReservedCodeCacheSize=96m"
 ]
 if (isMac) args << "-d32";
diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant
index b090f7a..7845d32 100644
--- a/build/scripts/utils.gant
+++ b/build/scripts/utils.gant
@@ -56,6 +56,7 @@
 binding.setVariable("mem32", "-server -Xms128m -Xmx512m -XX:MaxPermSize=250m -XX:ReservedCodeCacheSize=150m")
 binding.setVariable("mem64", "-Xms128m -Xmx750m -XX:MaxPermSize=350m -XX:ReservedCodeCacheSize=225m")
 binding.setVariable("common_vmoptions", "-ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true " +
+                                        "-Didea.project.structure.max.errors.to.show=0 " +
                                         "-Djsse.enableSNIExtension=false " +
                                         "-XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50")
 
@@ -167,7 +168,10 @@
 
 binding.setVariable("notifyArtifactBuilt", { String artifactPath ->
   if (!artifactPath.startsWith(home)) {
-    projectBuilder.error("Artifact path $artifactPath should start with $home")
+    // AndroidStudio: make this to be just an info as the out folder is typically
+    // not in the home folder
+    projectBuilder.info("Artifact path $artifactPath should start with $home")
+    return
   }
   def relativePath = artifactPath.substring(home.length())
   if (relativePath.startsWith("/")) {
@@ -221,7 +225,8 @@
 
 binding.setVariable("wireBuildDate", { String buildNumber, String appInfoFile ->
   ant.tstamp()
-  patchFiles([appInfoFile], ["BUILD_NUMBER": buildNumber, "BUILD_DATE": DSTAMP])
+  patchFiles([appInfoFile], ["BUILD_NUMBER": buildNumber, "BUILD_DATE": DSTAMP,
+          "PACKAGE_CODE": buildNumber.substring(0, buildNumber.indexOf('-'))])
 })
 
 binding.setVariable("commonJvmArgs", {
@@ -232,9 +237,10 @@
    "-Xbootclasspath/p:${projectBuilder.moduleOutput(findModule("boot"))}",
    "-XX:+HeapDumpOnOutOfMemoryError",
    "-Didea.system.path=${p("teamcity.build.tempDir")}/system",
-   "-Didea.config.path=${p("teamcity.build.tempDir")}/config",
-   "-Xdebug",
-   "-Xrunjdwp:transport=dt_socket,server=y,suspend=$suspendUntilDebuggerConnect,address=$debugPort"]
+   "-Didea.config.path=${p("teamcity.build.tempDir")}/config"]
+   // We don't want this on the Jenkins build server
+   // "-Xdebug",
+   // "-Xrunjdwp:transport=dt_socket,server=y,suspend=$suspendUntilDebuggerConnect,address=$debugPort"]
 })
 
 binding.setVariable("classPathLibs", [
@@ -402,6 +408,9 @@
     replacefilter(token: "@@bundle_name@@", value: fullName)
     replacefilter(token: "@@bundle_identifier@@", value: args.bundleIdentifier)
     replacefilter(token: "@@year@@", value: "$todayYear")
+    replacefilter(token: "@@company_name@@", value: args.companyName)
+    replacefilter(token: "@@min_year@@", value: "2013")
+    replacefilter(token: "@@max_year@@", value: "$todayYear")
     replacefilter(token: "@@version@@", value: version)
     replacefilter(token: "@@vmoptions@@", value: vmOptions)
     replacefilter(token: "@@idea_properties@@", value: coreProperties)
@@ -429,8 +438,8 @@
 
 binding.setVariable("winScripts", { String target, String home, String name, Map args ->
   String fullName = args.fullName != null ? args.fullName : p("component.names.fullname")
-  String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase()
-  String vm_options = args.vm_options != null ? args.vm_options : "${p("component.names.product").toLowerCase()}.exe"
+  String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase().replace(" ", "_")
+  String vm_options = args.vm_options != null ? args.vm_options : "${p("component.names.product").toLowerCase().replace(" ", "-")}.exe"
   if (vm_options.endsWith(".exe")) {
     vm_options = vm_options.replace(".exe", "%BITS%.exe")
   }
@@ -503,14 +512,19 @@
   ant.fixcrlf(srcdir: "$target/bin", includes: "*.sh", eol: "unix")
 })
 
-binding.setVariable("winVMOptions", { String target, String system_selector, String name, String name64 = null ->
+binding.setVariable("winVMOptions", { String target, Map args, String name, String name64 = null ->
   if (name != null) {
-    def options = isEap() && system_selector != null ? vmOptions32yjp(system_selector) : vmOptions32()
+    def options = vmOptions32()
+    options = options.replace(" -XX:+UseCodeCacheFlushing", "")
+    options += " -Didea.platform.prefix=" + args.platform_prefix
+    options += " -Didea.paths.selector="  + args.system_selector
     ant.echo(file: "$target/bin/${name}.vmoptions", message: options.replace(' ', '\n'))
   }
 
   if (name64 != null) {
-    def options = isEap() && system_selector != null ? vmOptions64yjp(system_selector) : vmOptions64()
+    def options = vmOptions64()
+    options += " -Didea.platform.prefix=" + args.platform_prefix
+    options += " -Didea.paths.selector="  + args.system_selector
     ant.echo(file: "$target/bin/${name64}.vmoptions", message: options.replace(' ', '\n'))
   }
 
@@ -534,6 +548,7 @@
                    ["product_full": fullName,
                     "product": p("component.names.product").toLowerCase(),
                     "system_selector": args.system_selector,
+                    "script_name" : args.script_name,
                     "settings_dir": settings_dir], "@@")
   ant.fixcrlf(file: "$target/bin/Install-Linux-tar.txt", eol: "unix")
 })
@@ -690,14 +705,14 @@
   return buff.toString()
 }
 
-binding.setVariable("buildWinZip", { String zipPath, List paths ->
+binding.setVariable("buildWinZip", { String zipRoot, String zipPath, List paths ->
   projectBuilder.stage(".win.zip")
 
   fixIdeaPropertiesEol(paths, "dos")
 
   ant.zip(zipfile: zipPath) {
     paths.each {
-      fileset(dir: it)
+      zipfileset(dir: it, prefix: zipRoot)
     }
   }
 
@@ -816,6 +831,14 @@
   }
 })
 
+binding.setVariable("layoutUpdater", { String target, String jarName = "updater.jar" ->
+  layout(target) {
+    jar(jarName) {
+      module("updater")
+    }
+  }
+})
+
 binding.setVariable("collectUsedJars", { List modules, List approvedJars, List forbiddenJars, List modulesToBuild ->
   def usedJars = new HashSet();
 
diff --git a/build_ide_ext.sh b/build_ide_ext.sh
new file mode 100755
index 0000000..bc8109a
--- /dev/null
+++ b/build_ide_ext.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# Expected arguments:
+# $1 = out_dir
+# $2 = qualifier (ignored, optional)
+# $3 = build_number or preview-<build_number>
+# $4 = --target ...
+
+PROG_DIR=$(dirname "$0")
+
+DEST=""
+QUAL=""
+BNUM=""
+TARGET=""
+
+function die() {
+  echo "$*" > /dev/stderr
+  echo "Usage: $0 [--keep] dest_dir [date] build_number [--target build]" > /dev/stderr
+  exit 1
+}
+
+while [[ -n "$1" ]]; do
+  if [[ "$1" == "--target" ]]; then
+    shift
+    TARGET="$1"
+  elif [[ "${1:0:2}" == "--" ]]; then
+    die "[$0] Unknown parameter: $1"
+  elif [[ -z "$DEST" ]]; then
+    DEST="$1"
+  elif [[ -z "$QUAL" ]]; then
+    QUAL="$1"
+  elif [[ -z "$BNUM" ]]; then
+    BNUM="$1"
+  else
+    die "[$0] Unknown parameter: $1"
+  fi
+  shift
+done
+
+if [[ -z $BNUM && -n $QUAL ]]; then
+  BNUM="$QUAL"
+  QUAL=""
+fi
+BNUM="${BNUM/preview-/}"
+
+if [[ -z "$DEST" ]]; then die "## Error: Missing dest_dir"; fi
+if [[ -z "$BNUM" ]]; then die "## Error: Missing build_number"; fi
+
+cd $PROG_DIR
+
+OUT="../../out/host/android-studio"
+mkdir -p "$OUT"
+
+ANT="java -jar lib/ant/lib/ant-launcher.jar -f build.xml"
+
+echo "## Building android-studio ##"
+echo "## Dest dir : $DEST"
+echo "## Qualifier: $QUAL"
+echo "## Build Num: $BNUM"
+echo "## Target   : $TARGET"
+echo
+
+$ANT "-Dout=$OUT" "-DbuildNumber=$BNUM" $TARGET
+
+echo "## Copying android-studio destination files"
+cp -rfv $OUT/artifacts/android-studio* $DEST/
+cp -rfv $OUT/updater-full.jar $DEST/android-studio-updater.jar
diff --git a/build_studio.sh b/build_studio.sh
new file mode 100755
index 0000000..d7bed52
--- /dev/null
+++ b/build_studio.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# Expected arguments:
+# $1 = out_dir
+# $2 = dist_dir
+# $3 = build_number
+
+PROG_DIR=$(dirname "$0")
+
+function die() {
+  echo "$*" > /dev/stderr
+  echo "Usage: $0 <out_dir> <dest_dir> <build_number>" > /dev/stderr
+  exit 1
+}
+
+while [[ -n "$1" ]]; do
+  if [[ -z "$OUT" ]]; then
+    OUT="$1"
+  elif [[ -z "$DIST" ]]; then
+    DIST="$1"
+  elif [[ -z "$BNUM" ]]; then
+    BNUM="$1"
+  else
+    die "[$0] Unknown parameter: $1"
+  fi
+  shift
+done
+
+if [[ -z "$OUT" ]]; then die "## Error: Missing out folder"; fi
+if [[ -z "$DIST" ]]; then die "## Error: Missing destination folder"; fi
+if [[ -z "$BNUM" ]]; then die "## Error: Missing build number"; fi
+
+cd "$PROG_DIR"
+
+mkdir -p "$OUT"
+
+ANT="java -jar lib/ant/lib/ant-launcher.jar -f build.xml"
+
+echo "## Building android-studio ##"
+echo "## Dest dir : $DIST"
+echo "## Qualifier: $QUAL"
+echo "## Build Num: $BNUM"
+echo
+
+$ANT "-Dout=$OUT" "-DbuildNumber=$BNUM"
+
+echo "## Copying android-studio destination files"
+cp -rfv "$OUT"/artifacts/android-studio* "$DIST"/
+cp -rfv "$OUT"/updater-full.jar "$DIST"/android-studio-updater.jar
diff --git a/community-main.iml b/community-main.iml
index a42803e..9aad39f 100644
--- a/community-main.iml
+++ b/community-main.iml
@@ -82,6 +82,8 @@
     <orderEntry type="module" module-name="tasks-tests" />
     <orderEntry type="module" module-name="github" />
     <orderEntry type="module" module-name="hg4idea" />
+    <orderEntry type="module" module-name="android" />
+    <orderEntry type="module" module-name="adt-branding" />
     <orderEntry type="module" module-name="relaxng" />
     <orderEntry type="module" module-name="gradle" />
     <orderEntry type="module" module-name="remote-servers-impl" />
@@ -99,6 +101,8 @@
     <orderEntry type="module" module-name="ui-designer-jps-plugin" scope="TEST" />
     <orderEntry type="module" module-name="java-tests" scope="TEST" />
     <orderEntry type="module" module-name="community-tests" scope="TEST" />
+    <orderEntry type="module" module-name="google-cloud-tools" />
+    <orderEntry type="module" module-name="google-login" />
     <orderEntry type="module" module-name="jira" />
     <orderEntry type="module" module-name="java-decompiler" />
     <orderEntry type="module" module-name="structuralsearch" />
diff --git a/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefClass.java b/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefClass.java
index 3e9044e..856285a 100644
--- a/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefClass.java
+++ b/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefClass.java
@@ -62,6 +62,9 @@
 
   boolean isTestCase();
 
+  /** Returns true if this class extends one of the Android framework classes that must be public */
+  boolean isAndroidPublic();
+
   boolean isLocalClass();
 
   boolean isSelfInheritor(PsiClass psiClass);
diff --git a/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefJavaManager.java b/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefJavaManager.java
index 51ea666..9ce3a61 100644
--- a/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefJavaManager.java
+++ b/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefJavaManager.java
@@ -71,6 +71,19 @@
 
   public abstract PsiClass getServlet();
 
+  // Android Framework APIs that apps extend and where the subclasses must be public
+  // such that the framework can instantiate them
+
+  public abstract PsiClass getAndroidView();
+  public abstract PsiClass getAndroidActivity();
+  public abstract PsiClass getAndroidService();
+  public abstract PsiClass getAndroidBackupAgent();
+  public abstract PsiClass getAndroidContentProvider();
+  public abstract PsiClass getAndroidReceiver();
+  public abstract PsiClass getAndroidFragment(boolean support);
+  public abstract PsiClass getAndroidActionProvider();
+  public abstract PsiClass getAndroidParcelable();
+
   public abstract EntryPointsManager getEntryPointsManager();
 
   @NotNull
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java
index 13a18f0..ddaeeb7 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java
@@ -56,6 +56,7 @@
   private static final int IS_SERVLET_MASK   = 0x400000;
   private static final int IS_TESTCASE_MASK  = 0x800000;
   private static final int IS_LOCAL_MASK     = 0x1000000;
+  private static final int IS_ANDROID_MASK   = 0x2000000;
 
   private Set<RefClass> myBases; // singleton (to conserve the memory) or THashSet
   private Set<RefClass> mySubClasses; // singleton (to conserve the memory) or THashSet
@@ -139,6 +140,26 @@
       }
     }
 
+    // The Android framework has a number of classes that it wants to
+    // instantiate so it requires these classes to be public, even if
+    // code analysis suggests that that these are only referenced from
+    // within the same package.  Unfortunately these do not all extend the
+    // same set of base classes, so we need to check all these cases
+    // independently.
+    RefJavaManager refManager = getRefJavaManager();
+    if (inheritsFrom(psiClass, refManager.getAndroidActivity())
+      || inheritsFrom(psiClass, refManager.getAndroidService())
+      || inheritsFrom(psiClass, refManager.getAndroidView())
+      || inheritsFrom(psiClass, refManager.getAndroidFragment(false))
+      || inheritsFrom(psiClass, refManager.getAndroidFragment(true))
+      || inheritsFrom(psiClass, refManager.getAndroidReceiver())
+      || inheritsFrom(psiClass, refManager.getAndroidContentProvider())
+      || inheritsFrom(psiClass, refManager.getAndroidParcelable())
+      || inheritsFrom(psiClass, refManager.getAndroidBackupAgent())
+      || inheritsFrom(psiClass, refManager.getAndroidActionProvider())) {
+      setAndroidPublic(true);
+    }
+
     for (PsiMethod psiMethod : psiMethods) {
       RefMethod refMethod = (RefMethod)getRefManager().getReference(psiMethod);
 
@@ -187,6 +208,10 @@
     }
   }
 
+  private static boolean inheritsFrom(@NotNull PsiClass c1, @Nullable PsiClass c2) {
+    return c2 != null && c1.isInheritor(c2, true);
+  }
+
   private static ServerPageFile getJspFile(PsiClass psiClass) {
     final PsiFile psiFile = PsiUtilCore.getTemplateLanguageFile(psiClass);
     return psiFile instanceof ServerPageFile ? (ServerPageFile)psiFile : null;
@@ -491,6 +516,11 @@
   }
 
   @Override
+  public boolean isAndroidPublic() {
+    return checkFlag(IS_ANDROID_MASK);
+  }
+
+  @Override
   public boolean isTestCase() {
     return checkFlag(IS_TESTCASE_MASK);
   }
@@ -557,6 +587,10 @@
     setFlag(servlet, IS_SERVLET_MASK);
   }
 
+  private void setAndroidPublic(boolean android) {
+    setFlag(android, IS_ANDROID_MASK);
+  }
+
   private void setTestCase(boolean testCase) {
     setFlag(testCase, IS_TESTCASE_MASK);
   }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
index d929166..341f44a 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
@@ -46,6 +46,16 @@
   private PsiMethod myAppAgentmainPattern;
   private PsiClass myApplet;
   private PsiClass myServlet;
+  private PsiClass myAndroidActivity;
+  private PsiClass myAndroidService;
+  private PsiClass myAndroidBackupAgent;
+  private PsiClass myAndroidFragment;
+  private PsiClass myAndroidV4Fragment;
+  private PsiClass myAndroidContentProvider;
+  private PsiClass myAndroidReceiver;
+  private PsiClass myAndroidView;
+  private PsiClass myAndroidActionProvider;
+  private PsiClass myAndroidParcelable;
   private RefPackage myDefaultPackage;
   private THashMap<String, RefPackage> myPackages;
   private final RefManagerImpl myRefManager;
@@ -66,9 +76,23 @@
       LOG.error(e);
     }
 
-    myApplet = JavaPsiFacade.getInstance(psiManager.getProject()).findClass("java.applet.Applet", GlobalSearchScope.allScope(project));
-    myServlet = JavaPsiFacade.getInstance(psiManager.getProject()).findClass("javax.servlet.Servlet", GlobalSearchScope.allScope(project));
+    GlobalSearchScope scope = GlobalSearchScope.allScope(project);
+    JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(psiManager.getProject());
+    myApplet = psiFacade.findClass("java.applet.Applet", scope);
+    myServlet = psiFacade.findClass("javax.servlet.Servlet", scope);
 
+    // Android Framework APIs that apps extend and where the subclasses must be public
+    // such that the framework can instantiate them
+    myAndroidActivity = psiFacade.findClass("android.app.Activity", scope);
+    myAndroidService = psiFacade.findClass("android.app.Service", scope);
+    myAndroidFragment = psiFacade.findClass("android.app.Fragment", scope);
+    myAndroidV4Fragment = psiFacade.findClass("android.support.v4.app.Fragment", scope);
+    myAndroidContentProvider = psiFacade.findClass("android.content.ContentProvider", scope);
+    myAndroidReceiver = psiFacade.findClass("android.content.BroadcastReceiver", scope);
+    myAndroidView = psiFacade.findClass("android.view.View", scope);
+    myAndroidActionProvider = psiFacade.findClass("android.view.ActionProvider", scope);
+    myAndroidParcelable = psiFacade.findClass("android.os.Parcelable", scope);
+    myAndroidBackupAgent = psiFacade.findClass("android.app.backup.BackupAgent", scope);
   }
 
   @Override
@@ -158,6 +182,51 @@
   }
 
   @Override
+  public PsiClass getAndroidActivity() {
+    return myAndroidActivity;
+  }
+
+  @Override
+  public PsiClass getAndroidService() {
+    return myAndroidService;
+  }
+
+  @Override
+  public PsiClass getAndroidBackupAgent() {
+    return myAndroidBackupAgent;
+  }
+
+  @Override
+  public PsiClass getAndroidFragment(boolean support) {
+    return support ? myAndroidV4Fragment : myAndroidFragment;
+  }
+
+  @Override
+  public PsiClass getAndroidContentProvider() {
+    return myAndroidContentProvider;
+  }
+
+  @Override
+  public PsiClass getAndroidReceiver() {
+    return myAndroidReceiver;
+  }
+
+  @Override
+  public PsiClass getAndroidView() {
+    return myAndroidView;
+  }
+
+  @Override
+  public PsiClass getAndroidActionProvider() {
+    return myAndroidActionProvider;
+  }
+
+  @Override
+  public PsiClass getAndroidParcelable() {
+    return myAndroidParcelable;
+  }
+
+  @Override
   public RefParameter getParameterReference(PsiParameter param, int index) {
     LOG.assertTrue(myRefManager.isValidPointForReference(), "References may become invalid after process is finished");
     RefElement ref = myRefManager.getFromRefTable(param);
@@ -203,6 +272,16 @@
     myAppPremainPattern = null;
     myAppAgentmainPattern = null;
     myServlet = null;
+    myAndroidActivity = null;
+    myAndroidService = null;
+    myAndroidBackupAgent = null;
+    myAndroidFragment = null;
+    myAndroidV4Fragment = null;
+    myAndroidContentProvider = null;
+    myAndroidReceiver = null;
+    myAndroidView = null;
+    myAndroidActionProvider = null;
+    myAndroidParcelable = null;
     myDefaultPackage = null;
     myProjectIterator = null;
   }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
index fd66f28..aa772f33 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
@@ -44,7 +44,6 @@
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.usageView.UsageViewTypeLocation;
 import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.VisibilityUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -179,6 +178,10 @@
         RefClass refClass = (RefClass) refElement;
         if (refClass.isAnonymous() || refClass.isEntry() || refClass.isTestCase() || refClass.isServlet() || refClass.isApplet() || refClass.isLocalClass()) return null;
         if (isTopLevelClass(refClass) && !SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES) return null;
+
+        if (refClass.isAndroidPublic()) {
+          return null;
+        }
       }
 
       //ignore unreferenced code. They could be a potential entry points.
diff --git a/platform/bootstrap/src/com/intellij/idea/Main.java b/platform/bootstrap/src/com/intellij/idea/Main.java
old mode 100644
new mode 100755
index ce8a2d0..fd72b55
--- a/platform/bootstrap/src/com/intellij/idea/Main.java
+++ b/platform/bootstrap/src/com/intellij/idea/Main.java
@@ -17,6 +17,7 @@
 
 import com.intellij.ide.Bootstrap;
 import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.SystemInfoRt;
 import com.intellij.openapi.util.io.FileUtilRt;
@@ -26,11 +27,13 @@
 import javax.swing.*;
 import java.awt.*;
 import java.io.*;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
 import java.util.List;
 import java.util.Locale;
 
+
 @SuppressWarnings({"UseOfSystemOutOrSystemErr", "MethodNamesDifferingOnlyByCase"})
 public class Main {
   public static final int UPDATE_FAILED = 1;
@@ -43,6 +46,8 @@
   private static final String PLATFORM_PREFIX_PROPERTY = "idea.platform.prefix";
   private static final String[] NO_ARGS = {};
 
+  private static final String MAIN_LOG_PROPERTY = "com.intellij.idea.Main.DelayedLog";
+
   private static boolean isHeadless;
   private static boolean isCommandLine;
 
@@ -68,8 +73,9 @@
           installPatch();
         }
         catch (Throwable t) {
+          appendLog("Exception: " + t.toString() + '\n');
           showMessage("Update Failed", t);
-          System.exit(UPDATE_FAILED);
+          exit(UPDATE_FAILED);
         }
       }
     }
@@ -79,10 +85,15 @@
     }
     catch (Throwable t) {
       showMessage("Start Failed", t);
-      System.exit(STARTUP_EXCEPTION);
+      exit(STARTUP_EXCEPTION);
     }
   }
 
+  private static void exit(int code) {
+    dumpDelayedLogging();
+    System.exit(code);
+  }
+
   public static boolean isHeadless() {
     return isHeadless;
   }
@@ -130,13 +141,19 @@
     File patchCopy = new File(tempDir, patchFileName + "_copy");
     File log4jCopy = new File(tempDir, "log4j.jar." + platform + "_copy");
     if (!FileUtilRt.delete(patchCopy) || !FileUtilRt.delete(log4jCopy)) {
+      appendLog("Cannot delete temporary files in " + tempDir);
       throw new IOException("Cannot delete temporary files in " + tempDir);
     }
 
     File patch = new File(tempDir, patchFileName);
+    appendLog("[Patch] Original patch %s: %s\n", patch.exists() ? "exists" : "does not exist",
+              patch.getAbsolutePath());
     if (!patch.exists()) return;
     File log4j = new File(PathManager.getLibPath(), "log4j.jar");
-    if (!log4j.exists()) throw new IOException("Log4J missing: " + log4j);
+    if (!log4j.exists()) {
+      appendLog("Log4J missing: " + log4j);
+      throw new IOException("Log4J missing: " + log4j);
+    }
     copyFile(patch, patchCopy, true);
     copyFile(log4j, log4jCopy, false);
 
@@ -151,7 +168,7 @@
 
       //noinspection SpellCheckingInspection
       Collections.addAll(args,
-                         System.getProperty("java.home") + "/bin/java",
+                         System.getProperty("java.home") + "/bin/java".replace('/', File.separatorChar),
                          "-Xmx500m",
                          "-classpath",
                          patchCopy.getPath() + File.pathSeparator + log4jCopy.getPath(),
@@ -162,14 +179,19 @@
                          "install",
                          PathManager.getHomePath());
 
+      appendLog("[Patch] Restarted cmd: %s\n", args.toString());
+
       status = Restarter.scheduleRestart(ArrayUtilRt.toStringArray(args));
+
+      appendLog("[Patch] Restarted status: %d\n", status);
     }
     else {
+      appendLog("[Patch] Restart is not supported\n");
       String message = "Patch update is not supported - please do it manually";
       showMessage("Update Error", message, true);
     }
 
-    System.exit(status);
+    exit(status);
   }
 
   private static void copyFile(File original, File copy, boolean move) throws IOException {
@@ -193,6 +215,12 @@
     message.append(studio ? "code.google.com/p/android/issues" : "youtrack.jetbrains.com");
     message.append("\n\n");
     t.printStackTrace(new PrintWriter(message));
+
+    String p = System.getProperty(MAIN_LOG_PROPERTY);
+    if (p != null) {
+      message.append('\n').append(p);
+    }
+
     showMessage(title, message.toString(), true);
   }
 
@@ -226,4 +254,60 @@
       JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), scrollPane, title, type);
     }
   }
+
+
+  /**
+   * Appends the non-null string to an internal log property because at
+   * this point when the updater runs the main logger hasn't been setup yet.
+   *
+   * We use a system property rather than a global static variable because
+   * both codes do not run in the same ClassLoader and don't have the same
+   * globals.
+   */
+  private static void appendLog(String message, Object...params) {
+    String p = System.getProperty(MAIN_LOG_PROPERTY);
+    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
+    String s = dateFormat.format(new Date()) + String.format(message, params);
+    if (p == null) {
+      p = s;
+    } else {
+      p += s;
+    }
+    System.setProperty(MAIN_LOG_PROPERTY, p);
+  }
+
+  /** Invoked by Main to dump the log when the Main is exiting right away.
+   * The normal IDE log will not be used. */
+  public static void dumpDelayedLogging() {
+    String p = System.getProperty(MAIN_LOG_PROPERTY);
+    if (p != null) {
+      System.clearProperty(MAIN_LOG_PROPERTY);
+      File log = new File(PathManager.getLogPath());
+      //noinspection ResultOfMethodCallIgnored
+      log.mkdirs();
+      log = new File(log, "idea_patch.log");
+      FileOutputStream fos = null;
+      try {
+        //noinspection IOResourceOpenedButNotSafelyClosed
+        fos = new FileOutputStream(log, true /*append*/);
+        fos.write(p.getBytes("UTF-8"));
+      } catch (IOException ignore) {
+      } finally {
+        if (fos != null) {
+          try { fos.close(); } catch (IOException ignored) {}
+        }
+      }
+    }
+  }
+
+  /** Invoked by StartupUtil once the main logger is setup. */
+  public static void dumpDelayedLogging(Logger log) {
+    if (log != null) {
+      String p = System.getProperty(MAIN_LOG_PROPERTY);
+      if (p != null) {
+        log.info(p);
+        System.clearProperty(MAIN_LOG_PROPERTY);
+      }
+    }
+  }
 }
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java
index 6e1740c..f240681 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java
@@ -18,6 +18,7 @@
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.util.containers.ContainerUtilRt;
 import com.intellij.util.messages.Topic;
 import org.jetbrains.annotations.NotNull;
@@ -107,6 +108,9 @@
         }
       }
     }
+    if (ps == null) {
+      ps = myLinkedProjectsSettings.get(FileUtil.toSystemIndependentName(linkedProjectPath));
+    }
     return ps;
   }
 
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java
index 695c2a7..9bbaa27 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java
@@ -310,6 +310,21 @@
     });
   }
 
+  // Android Studio: Is the given file a file we should ignore during batch inspections?
+  private static final String EXPLODED_AAR = "exploded-aar";
+  private static boolean isIgnoredFile(@NotNull PsiFile psiFile) {
+    VirtualFile file = psiFile.getVirtualFile();
+    while (file != null) {
+      if (EXPLODED_AAR.equals(file.getName())) {
+        return true;
+      } else {
+        file = file.getParent();
+      }
+    }
+
+    return false;
+  }
+
   @Override
   protected void runTools(@NotNull AnalysisScope scope, boolean runGlobalToolsOnly) {
     final InspectionManagerEx inspectionManager = (InspectionManagerEx)InspectionManager.getInstance(getProject());
@@ -343,6 +358,33 @@
           throw new ProcessCanceledException();
         }
 
+        // Android Studio tweak:
+        // Most "outputs" (such as build/intermediates/) are marked as generated
+        // source roots, which means IntelliJ won't scan those folders for
+        // warnings.
+        //
+        // However, AAR libraries are extracted into special build folders
+        // (currently build/intermediates/exploded-aar) which are *not* marked as
+        // generated; that's necessary such that those folders are scanned (for
+        // indexing purposes), handled as potential go-to-declaration targets
+        // (since resource files there can contain for example themes extended in
+        // the user's application). Therefore, by default, IntelliJ will analyze
+        // all the files in the exploded AAR folders. When you have large
+        // libraries like appcompat or play services, this not only takes a lot
+        // of extra time to analyze. You also end up with a lot of errors in
+        // files you can't edit. For example, with appcompat, you end up with
+        // over 700 spelling mistake warnings, and with play services, you end up
+        // with over a hundred unused namespace warnings, and over a hundred tag
+        // has no children warnings!
+        //
+        // Therefore, in the below  this CL tweaks the batch analysis runner which iterates
+        // over PSI files to skip files that are found to be within an AAR
+        // folder. This removes all the false positives and speeds up code
+        // analysis quite significantly!
+        if (isIgnoredFile(file)) {
+          return;
+        }
+
         if (LOG.isDebugEnabled()) {
           LOG.debug("Running local inspections on " + virtualFile.getPath());
         }
diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java
index dc47793..0f47fbe 100644
--- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java
+++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java
@@ -224,7 +224,7 @@
 
   @Override
   public int getWeight() {
-    return 3;
+    return 200; // was 3, changed to 200 in Android Studio so that has a lower weight than the Android view.
   }
 
   @Override
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
index 14b0cc5..a0e96c5 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
@@ -993,6 +993,11 @@
       return getCorePluginSubmitter(reporters);
     }
     for (ErrorReportSubmitter reporter : reporters) {
+      /** Android Studio: Always use the android error reporter */
+      String canonicalName = reporter.getClass().getCanonicalName();
+      if (canonicalName != null && canonicalName.contains("android")) {
+        return reporter;
+      }
       final PluginDescriptor descriptor = reporter.getPluginDescriptor();
       if (descriptor != null && Comparing.equal(pluginId, descriptor.getPluginId())) {
         return reporter;
diff --git a/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java b/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java
index e49cef4..8c41a8e 100644
--- a/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java
+++ b/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java
@@ -65,7 +65,7 @@
   }
 
   private void checkJvm() {
-    if (StringUtil.containsIgnoreCase(System.getProperty("java.vm.name", ""), "OpenJDK") && !SystemInfo.isJavaVersionAtLeast("1.7")) {
+    if (StringUtil.containsIgnoreCase(System.getProperty("java.vm.name", ""), "OpenJDK")) {
       notifyUnsupportedJvm("unsupported.jvm.openjdk.message");
     }
     else if (StringUtil.endsWithIgnoreCase(System.getProperty("java.version", ""), "-ea")) {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
index fce491b..4a72eda 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
@@ -47,6 +47,7 @@
     urlTemplate = urlTemplate
       .replace("$BUILD", eap ? appInfo.getBuild().asStringWithoutProductCode() : appInfo.getBuild().asString())
       .replace("$TIMEZONE", System.getProperty("user.timezone"))
+      .replace("$VERSION", appInfo.getFullVersion())
       .replace("$EVAL", isEvaluationLicense() ? "true" : "false")
       .replace("$DESCR", getDescription());
     BrowserUtil.browse(urlTemplate, project);
diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
old mode 100644
new mode 100755
index 10f9c73..43c0a2d
--- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
+++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
@@ -130,6 +130,7 @@
     Logger log = Logger.getInstance(Main.class);
     startLogging(log);
     loadSystemLibraries(log);
+    Main.dumpDelayedLogging(log);
     fixProcessEnvironment(log);
 
     if (!Main.isHeadless()) {
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/updater/SendStatisticsProjectComponent.java b/platform/platform-impl/src/com/intellij/internal/statistic/updater/SendStatisticsProjectComponent.java
index 0e5ac83..28a17e2 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/updater/SendStatisticsProjectComponent.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/updater/SendStatisticsProjectComponent.java
@@ -71,18 +71,7 @@
       StatisticsNotificationManager.showNotification(statisticsService, myProject);
     }
     else if (StatisticsUploadAssistant.isSendAllowed() && StatisticsUploadAssistant.isTimeToSend()) {
-      StatisticsService serviceToUse = null;
-      StatisticsServiceEP[] extensions = StatisticsService.EP_NAME.getExtensions();
-      if (extensions.length > 1) {
-        LOG.warn(String.format("More than one stats service detected (%s). Falling back to the built-in one", Arrays.toString(extensions)));
-      }
-      else if (extensions.length == 1) {
-        serviceToUse = extensions[0].getInstance();
-      }
-      if (serviceToUse == null) {
-        serviceToUse = statisticsService;
-      }
-      runWithDelay(serviceToUse);
+      runWithDelay(statisticsService);
     }
   }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
index 51809ad..8120b06 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
@@ -132,6 +132,27 @@
         maxFile = file;
       }
     }
+
+    // Android Studio: Attempt to find user settings from earlier versions where the settings names
+    // are different from the current setting name
+    if (maxFile == null) {
+      File preview = new File(PathManager.getDefaultConfigPathFor("AndroidStudioPreview"));
+      File beta = new File(PathManager.getDefaultConfigPathFor("AndroidStudioBeta")); // relevant when we switch from beta to stable
+      for (File file : new File[] { preview, beta }) {
+        if (!file.isDirectory()) {
+          continue;
+        }
+        File options = new File(file, CONFIG_RELATED_PATH + OPTIONS_XML);
+        if (options.exists()) {
+          final long modified = options.lastModified();
+          if (modified > lastModified) {
+            lastModified = modified;
+            maxFile = file;
+          }
+        }
+      }
+    }
+
     return maxFile != null ? new File(maxFile, CONFIG_RELATED_PATH) : null;
   }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ChannelStatus.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ChannelStatus.java
old mode 100644
new mode 100755
index b7c133f..b4adf37
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ChannelStatus.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ChannelStatus.java
@@ -28,10 +28,25 @@
   @NonNls public static final String EAP_CODE = "eap";
   @NonNls public static final String RELEASE_CODE = "release";
 
-  public static final ChannelStatus EAP = new ChannelStatus(0, EAP_CODE, "Early Access Program");
-  public static final ChannelStatus MILESTONE = new ChannelStatus(1, "milestone", "Milestone Releases");
-  public static final ChannelStatus BETA = new ChannelStatus(2, "beta", "Beta Releases or Public Previews");
-  public static final ChannelStatus RELEASE = new ChannelStatus(3, RELEASE_CODE, "New Major Version Releases");
+  /**
+   * EAP is our Canary Channel.
+   * <p/>
+   * From the updates.xml description: <br/>
+   * Canary builds are the bleeding edge, released about weekly. While these builds do get tested,
+   * they are still subject to bugs, as we want people to see what's new as soon as possible.
+   * This is not recommended for production.
+   */
+  public static final ChannelStatus EAP = new ChannelStatus(0, EAP_CODE, "Canary Channel");
+  /**
+   * Milestone is our Dev Channel.
+   * <p/>
+   * From the updates.xml description: <br/>
+   * Dev channel builds are hand-picked older canary builds that survived the test of time.
+   * It's updated roughly every month.
+   */
+  public static final ChannelStatus MILESTONE = new ChannelStatus(1, "milestone", "Dev Channel");
+  public static final ChannelStatus BETA = new ChannelStatus(2, "beta", "Beta Channel");
+  public static final ChannelStatus RELEASE = new ChannelStatus(3, RELEASE_CODE, "Stable Channel");
 
   private static final List<ChannelStatus> ALL_TYPES = ContainerUtil.immutableList(RELEASE, BETA, MILESTONE, EAP);
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
old mode 100644
new mode 100755
index 83858cc..f1206ef
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.openapi.updateSettings.impl;
 
+import com.google.common.net.HttpHeaders;
 import com.intellij.diagnostic.IdeErrorsDialog;
 import com.intellij.ide.IdeBundle;
 import com.intellij.ide.plugins.*;
@@ -774,10 +775,31 @@
     String platform = PlatformUtils.getPlatformPrefix();
 
     File tempFile = FileUtil.createTempFile(platform, "patch", true);
+    LOG.info(String.format("[Patch] Download %s to %s", fileName, tempFile.getAbsolutePath()));
 
     OutputStream out = new BufferedOutputStream(new FileOutputStream(tempFile));
     try {
-      URLConnection connection = HttpConfigurable.getInstance().openConnection(new URL(new URL(getPatchesUrl()), fileName).toString());
+      String requestUrl = new URL(new URL(getPatchesUrl()), fileName).toString();
+      URLConnection connection;
+
+      int followCount = 2;
+      while(true) {
+        connection = HttpConfigurable.getInstance().openConnection(requestUrl);
+
+        if (connection instanceof HttpURLConnection) {
+          HttpURLConnection hcnx = (HttpURLConnection)connection;
+          int code = hcnx.getResponseCode();
+          if (code >= 301 && code <= 307 && --followCount >= 0) {
+            String loc = hcnx.getHeaderField(HttpHeaders.LOCATION);
+            if (loc != null) {
+              requestUrl = loc;
+              continue;
+            }
+          }
+        }
+        break;
+      }
+
       try {
         InputStream in = UrlConnectionUtil.getConnectionInputStreamWithException(connection, i);
         try {
@@ -819,6 +841,7 @@
     File patchFile = new File(FileUtil.getTempDirectory(), patchFileName);
     FileUtil.copy(tempFile, patchFile);
     FileUtil.delete(tempFile);
+    LOG.info(String.format("[Patch] moved to %s", patchFile.getAbsolutePath()));
   }
 
   public static Set<String> getDisabledToUpdatePlugins() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java
index 9c6c6a2..97082c3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java
@@ -16,6 +16,7 @@
 package com.intellij.openapi.updateSettings.impl;
 
 
+import com.google.common.net.HttpHeaders;
 import com.intellij.ide.IdeBundle;
 import com.intellij.ide.reporter.ConnectionException;
 import com.intellij.openapi.application.ApplicationManager;
@@ -31,6 +32,7 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLConnection;
 import java.util.concurrent.Callable;
@@ -68,10 +70,29 @@
 
           URL requestUrl = prepareRequestUrl(updateUrl);
 
-          URLConnection connection = requestUrl.openConnection();
-          connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
-          connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
-          final InputStream inputStream = connection.getInputStream();
+          URLConnection cnx;
+          int followCount = 2;
+          while(true) {
+            cnx = requestUrl.openConnection();
+            cnx.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+            cnx.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+
+            if (cnx instanceof HttpURLConnection) {
+              HttpURLConnection hcnx = (HttpURLConnection)cnx;
+              int code = hcnx.getResponseCode();
+              if (code >= 301 && code <= 307 && --followCount >= 0) {
+                String loc = hcnx.getHeaderField(HttpHeaders.LOCATION);
+                if (loc != null) {
+                  prepareUrl(loc);
+                  requestUrl = prepareRequestUrl(loc);
+                  continue;
+                }
+              }
+            }
+            break;
+          }
+
+          final InputStream inputStream = cnx.getInputStream();
           Reader reader = new InputStreamReader(inputStream);
           try {
             return new UpdatesInfo(JDOMUtil.loadDocument(inputStream).getRootElement());
diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties
index e5a1ecc..2c0a81a 100644
--- a/platform/platform-resources-en/src/messages/IdeBundle.properties
+++ b/platform/platform-resources-en/src/messages/IdeBundle.properties
@@ -1105,7 +1105,7 @@
 browsers.settings=Web Browsers
 updates.check.period.on.exit=On every exit
 
-unsupported.jvm.openjdk.message=OpenJDK 6 is not supported. Please use Oracle Java or newer OpenJDK.
+unsupported.jvm.openjdk.message=OpenJDK shows intermittent performance and UI issues. We recommend using the Oracle JRE/JDK.
 unsupported.jvm.ea.message=Early Access Java versions may cause compatibility issues. Please use stable release.
 unsupported.jvm.link=<br/><a href="#">Do not show again</a>.
 
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
index be9f257..17ad0f7 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
@@ -703,6 +703,12 @@
                      key="simplifiable.conditional.expression.display.name" groupBundle="messages.InspectionsBundle"
                      groupKey="group.names.control.flow.issues" enabledByDefault="true" level="WARNING"
                      implementationClass="com.siyeh.ig.controlflow.SimplifiableConditionalExpressionInspection"/>
+    <!-- Moved in Android Studio over to the Code Style category where it more logically belongs since this is the only one enabled by default
+         in the J2ME category and it's really just a code style issue (and there are 4 other Simplifiable-Something conditions here) -->
+    <localInspection language="JAVA" shortName="SimplifiableIfStatement" bundle="com.siyeh.InspectionGadgetsBundle"
+                     key="simplifiable.if.statement.display.name" groupBundle="messages.InspectionsBundle"
+                     groupKey="group.names.code.style.issues" enabledByDefault="true" level="WARNING"
+                     implementationClass="com.siyeh.ig.j2me.SimplifiableIfStatementInspection"/>
     <localInspection language="JAVA" shortName="SwitchStatementDensity" bundle="com.siyeh.InspectionGadgetsBundle"
                      key="switch.statement.density.display.name" groupBundle="messages.InspectionsBundle"
                      groupKey="group.names.control.flow.issues" enabledByDefault="false" level="WARNING"
@@ -1191,10 +1197,6 @@
                      bundle="com.siyeh.InspectionGadgetsBundle" key="recordstore.opened.not.safely.closed.display.name"
                      groupBundle="messages.InspectionsBundle" groupKey="group.names.j2me.issues" enabledByDefault="false" level="WARNING"
                      implementationClass="com.siyeh.ig.j2me.RecordStoreResourceInspection"/>
-    <localInspection language="JAVA" shortName="SimplifiableIfStatement" bundle="com.siyeh.InspectionGadgetsBundle"
-                     key="simplifiable.if.statement.display.name" groupBundle="messages.InspectionsBundle"
-                     groupKey="group.names.j2me.issues" enabledByDefault="true" level="WARNING"
-                     implementationClass="com.siyeh.ig.j2me.SimplifiableIfStatementInspection"/>
     <localInspection language="JAVA" shortName="SingleCharacterStartsWith" bundle="com.siyeh.InspectionGadgetsBundle"
                      key="single.character.startswith.display.name" groupBundle="messages.InspectionsBundle"
                      groupKey="group.names.j2me.issues" enabledByDefault="false" level="WARNING"
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/SimplifiableIfStatement.html b/plugins/InspectionGadgets/src/inspectionDescriptions/SimplifiableIfStatement.html
index 398d5cb..9964296 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/SimplifiableIfStatement.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/SimplifiableIfStatement.html
@@ -1,8 +1,5 @@
 <html>
 <body>
-This inspection is intended for J2ME and other highly resource constrained environments.
-Applying the results of this inspection without consideration might have negative effects on code clarity and design.
-<p>
 Reports if statements of the form
 <b>if (<i>condition</i>) return true else return <i>foo</i></b>
 or <b>if (<i>condition</i>) return false else return <i>foo</i></b>.
@@ -13,4 +10,4 @@
 <p>
 
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/plugins/android/lib/guava-15.0.jar b/plugins/android/lib/guava-15.0.jar
new file mode 100644
index 0000000..eb9ef8a
--- /dev/null
+++ b/plugins/android/lib/guava-15.0.jar
Binary files differ
diff --git a/plugins/android/lib/jarutils.jar b/plugins/android/lib/jarutils.jar
new file mode 100644
index 0000000..1259ccf
--- /dev/null
+++ b/plugins/android/lib/jarutils.jar
Binary files differ
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
index 30fb81a..d17b9fd 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
@@ -331,6 +331,10 @@
         }
       }
 
+      if (result == GlobalSearchScope.EMPTY_SCOPE) {
+        result = baseScope;
+      }
+
       String modulePath = module.getOptionValue(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY);
       if(modulePath == null) return result;
 
diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml
index db15a38..cabf8e7 100644
--- a/plugins/groovy/src/META-INF/plugin.xml
+++ b/plugins/groovy/src/META-INF/plugin.xml
@@ -1488,7 +1488,7 @@
     <projectStructureDetector implementation="org.jetbrains.plugins.groovy.griffon.GriffonProjectStructureDetector"
                               order="before groovyDetector"/>
     <programRunner implementation="org.jetbrains.plugins.groovy.griffon.GriffonDebuggerRunner"/>
-    <configurationType implementation="org.jetbrains.plugins.groovy.griffon.GriffonRunConfigurationType"/>
+    <!-- <configurationType implementation="org.jetbrains.plugins.groovy.griffon.GriffonRunConfigurationType"/> -->
     <toolWindow id="Griffon View" anchor="left" secondary="false" icon="JetgroovyIcons.Griffon.GriffonToolWindow"
                 factoryClass="org.jetbrains.plugins.groovy.griffon.GriffonToolWindowFactory"
                 conditionClass="org.jetbrains.plugins.groovy.griffon.GriffonToolWindowFactory"/>
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java
index 199db3a..bfe3d14 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java
@@ -207,7 +207,8 @@
       throw new MavenServerProcessCanceledException();
     }
     catch (Exception e) {
-      throw new MavenServerIndexerException(wrapException(e));
+      // Disabled in Android Studio, no need to know about this exception
+      // throw new MavenServerIndexerException(wrapException(e));
     }
   }
 
diff --git a/plugins/maven/src/main/resources/META-INF/plugin.xml b/plugins/maven/src/main/resources/META-INF/plugin.xml
index 562bb3a..41a8ad3 100644
--- a/plugins/maven/src/main/resources/META-INF/plugin.xml
+++ b/plugins/maven/src/main/resources/META-INF/plugin.xml
@@ -64,8 +64,8 @@
     <stepsBeforeRunProvider implementation="org.jetbrains.idea.maven.tasks.MavenBeforeRunTasksProvider"/>
     <keymapExtension implementation="org.jetbrains.idea.maven.tasks.MavenKeymapExtension"/>
     <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
-    <configurationType implementation="org.jetbrains.idea.maven.execution.MavenRunConfigurationType"/>
-    <configurationProducer implementation="org.jetbrains.idea.maven.execution.MavenConfigurationProducer"/>
+    <!-- <configurationType implementation="org.jetbrains.idea.maven.execution.MavenRunConfigurationType"/>
+    <configurationProducer implementation="org.jetbrains.idea.maven.execution.MavenConfigurationProducer"/> -->
     <orderEnumerationHandlerFactory implementation="org.jetbrains.idea.maven.execution.MavenOrderEnumeratorHandler$FactoryImpl"/>
 
     <junitPatcher implementation="org.jetbrains.idea.maven.execution.MavenJUnitPatcher" />
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/CreationTool.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/CreationTool.java
index 83ed504..5f301ac7 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/CreationTool.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/CreationTool.java
@@ -16,8 +16,10 @@
 package com.intellij.designer.designSurface.tools;
 
 import com.intellij.designer.designSurface.OperationContext;
+import com.intellij.designer.model.RadComponent;
 
 import java.util.Collections;
+import java.util.List;
 
 /**
  * @author Alexander Lobas
@@ -49,6 +51,11 @@
 
   @Override
   protected void updateTarget() {
-    myTargetOperation.setComponent(myContext.getComponents().get(0));
+    if (myTargetOperation != null && myContext != null) {
+      List<RadComponent> components = myContext.getComponents();
+      if (components != null && !components.isEmpty()) {
+        myTargetOperation.setComponent(components.get(0));
+      }
+    }
   }
 }
\ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java b/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java
index a44a343..5ad9e44 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java
@@ -23,6 +23,7 @@
 import com.intellij.openapi.actionSystem.impl.ActionButton;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.wm.IdeFocusManager;
 import com.intellij.ui.IdeBorderFactory;
 import com.intellij.ui.PopupHandler;
@@ -85,7 +86,11 @@
     actionGroup.addSeparator();
 
     RestoreDefault restoreDefault = new RestoreDefault(myPropertyTable);
-    restoreDefault.registerCustomShortcutSet(actionManager.getAction(IdeActions.ACTION_DELETE).getShortcutSet(), myPropertyTable);
+    // Don't register ACTION_DELETE on Mac; on Mac, the default delete key is VK_DELETE rather than VK_BACK_SPACE
+    // which means users end up accidentally restoring to default when trying to edit inside property editors.
+    if (!SystemInfo.isMac) {
+      restoreDefault.registerCustomShortcutSet(actionManager.getAction(IdeActions.ACTION_DELETE).getShortcutSet(), myPropertyTable);
+    }
     actionGroup.add(restoreDefault);
 
     actionGroup.add(new ShowExpert(myPropertyTable));
diff --git a/resources-en/src/tips/Welcome.html b/resources-en/src/tips/Welcome.html
index 7301e94..6d8381a 100644
--- a/resources-en/src/tips/Welcome.html
+++ b/resources-en/src/tips/Welcome.html
@@ -4,7 +4,7 @@
 </head>
 <body>
     <h1>
-        Welcome to <span class="product">&productName;</span> <span class="version">&majorVersion;</span></h1>
+        Welcome to <span class="product">&productName;</span> <span class="version">&majorVersion;.&minorVersion;<</span></h1>
     <p>
         You can quickly get familiar with the main features of the IDE by reading these tips. You may try out
         the features described in the tips while this dialog stays open on the screen. If you close the dialog,
diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml
index 6b889d9..ac35522 100644
--- a/resources/src/META-INF/IdeaPlugin.xml
+++ b/resources/src/META-INF/IdeaPlugin.xml
@@ -1221,8 +1221,8 @@
     <favoriteNodeProvider implementation="com.intellij.ide.favoritesTreeView.PsiPackageFavoriteNodeProvider"/>
     <favoriteNodeProvider implementation="com.intellij.ide.favoritesTreeView.UsageFavoriteNodeProvider"/>
 
-    <configurationType implementation="com.intellij.execution.applet.AppletConfigurationType"/>
-    <configurationProducer implementation="com.intellij.execution.applet.AppletConfigurationProducer"/>
+    <!-- <configurationType implementation="com.intellij.execution.applet.AppletConfigurationType"/>
+    <configurationProducer implementation="com.intellij.execution.applet.AppletConfigurationProducer"/> -->
     <configurationType implementation="com.intellij.execution.application.ApplicationConfigurationType"/>
     <configurationType implementation="com.intellij.execution.jar.JarApplicationConfigurationType"/>
     <runConfigurationProducer implementation="com.intellij.execution.jar.JarApplicationConfigurationProducer"/>
diff --git a/updater/src/com/intellij/updater/BaseUpdateAction.java b/updater/src/com/intellij/updater/BaseUpdateAction.java
old mode 100644
new mode 100755
index 1d5e5a1..67a16f8e
--- a/updater/src/com/intellij/updater/BaseUpdateAction.java
+++ b/updater/src/com/intellij/updater/BaseUpdateAction.java
@@ -35,7 +35,13 @@
 
   protected void replaceUpdated(File from, File dest) throws IOException {
     // on OS X code signing caches seem to be associated with specific file ids, so we need to remove the original file.
-    if (!dest.delete()) throw new IOException("Cannot delete file " + dest);
+    if (!dest.delete()) {
+      if (Utils.isWindows()) {
+        throw new RetryException("Cannot delete file " + dest);
+      } else {
+        throw new IOException("Cannot delete file " + dest);
+      }
+    }
     Utils.copy(from, dest);
   }
 
diff --git a/updater/src/com/intellij/updater/CreateAction.java b/updater/src/com/intellij/updater/CreateAction.java
old mode 100644
new mode 100755
index e1a3fa1..5b0f8df
--- a/updater/src/com/intellij/updater/CreateAction.java
+++ b/updater/src/com/intellij/updater/CreateAction.java
@@ -59,7 +59,15 @@
 
   private static void prepareToWriteFile(File file) throws IOException {
     if (file.exists()) {
-      Utils.delete(file);
+      try {
+        Utils.delete(file);
+      } catch (IOException e) {
+        if (Utils.isWindows() && file.exists()) {
+          throw new RetryException(e);
+        } else {
+          throw e;
+        }
+      }
       return;
     }
 
diff --git a/updater/src/com/intellij/updater/DeleteAction.java b/updater/src/com/intellij/updater/DeleteAction.java
old mode 100644
new mode 100755
index 3dd1b85..286e471
--- a/updater/src/com/intellij/updater/DeleteAction.java
+++ b/updater/src/com/intellij/updater/DeleteAction.java
@@ -43,13 +43,23 @@
 
   @Override
   protected void doApply(ZipFile patchFile, File toFile) throws IOException {
-    Utils.delete(toFile);
+    try {
+      Utils.delete(toFile);
+    } catch (IOException e) {
+      if (Utils.isWindows() && toFile.exists()) {
+        throw new RetryException(e);
+      } else {
+        throw e;
+      }
+    }
   }
 
+  @Override
   protected void doBackup(File toFile, File backupFile) throws IOException {
     Utils.copy(toFile, backupFile);
   }
 
+  @Override
   protected void doRevert(File toFile, File backupFile) throws IOException {
     Utils.delete(toFile); // make sure there is no directory remained on this path (may remain from previous 'create' actions
     Utils.copy(backupFile, toFile);
diff --git a/updater/src/com/intellij/updater/Digester.java b/updater/src/com/intellij/updater/Digester.java
old mode 100644
new mode 100755
index 00792ce..ba6a470
--- a/updater/src/com/intellij/updater/Digester.java
+++ b/updater/src/com/intellij/updater/Digester.java
@@ -28,7 +28,8 @@
         zipFile = new ZipFile(file);
       }
       catch (IOException e) {
-        Runner.printStackTrace(e);
+        // If this isn't a zip file, this isn't really an error, merely an info.
+        Runner.infoStackTrace("Can't open file as zip file: " + file.getPath() + "\n", e);
         return doDigestRegularFile(file);
       }
 
diff --git a/updater/src/com/intellij/updater/RetryException.java b/updater/src/com/intellij/updater/RetryException.java
new file mode 100755
index 0000000..e13c4eb
--- /dev/null
+++ b/updater/src/com/intellij/updater/RetryException.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 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.intellij.updater;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown when an IOException arises when performing a patch
+ * action and it's likely that retrying will be successful.
+ */
+public class RetryException extends IOException {
+  public RetryException() {
+  }
+
+  public RetryException(String message) {
+    super(message);
+  }
+
+  public RetryException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public RetryException(Throwable cause) {
+    super(cause);
+  }
+}
diff --git a/updater/src/com/intellij/updater/Runner.java b/updater/src/com/intellij/updater/Runner.java
old mode 100644
new mode 100755
index 39e58e5..56a331b
--- a/updater/src/com/intellij/updater/Runner.java
+++ b/updater/src/com/intellij/updater/Runner.java
@@ -38,11 +38,22 @@
       create(oldVersionDesc, newVersionDesc, oldFolder, newFolder, patchFile, ignoredFiles, criticalFiles, optionalFiles);
     }
     else if (args.length >= 2 && "install".equals(args[0])) {
-      String destFolder = args[1];
+      // install [--exit0] <destination_folder>
+      int nextArg = 1;
+
+      // Default install exit code is SwingUpdaterUI.RESULT_REQUIRES_RESTART (42) unless overridden to be 0.
+      // This is used by testUI/build.gradle as gradle expects a javaexec to exit with code 0.
+      boolean useExitCode0 = false;
+      if (args[nextArg].equals("--exit0")) {
+        useExitCode0 = true;
+        nextArg++;
+      }
+
+      String destFolder = args[nextArg++];
       initLogger();
       logger.info("destFolder: " + destFolder);
 
-      install(destFolder);
+      install(useExitCode0, destFolder);
     }
     else {
       printUsage();
@@ -93,6 +104,10 @@
     }
   }
 
+  public static void infoStackTrace(String msg, Throwable e){
+    logger.info(msg, e);
+  }
+
   public static void printStackTrace(Throwable e){
     logger.error(e.getMessage(), e);
   }
@@ -115,8 +130,8 @@
   private static void printUsage() {
     System.err.println("Usage:\n" +
                        "create <old_version_description> <new_version_description> <old_version_folder> <new_version_folder>" +
-                       " <patch_file_name> [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
-                       "install <destination_folder> [log_directory]\n");
+                       " <patch_file_name> <log_directory> [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
+                       "install [--exit0] <destination_folder> [log_directory]\n");
   }
 
   private static void create(String oldBuildDesc,
@@ -127,9 +142,31 @@
                              List<String> ignoredFiles,
                              List<String> criticalFiles,
                              List<String> optionalFiles) throws IOException, OperationCancelledException {
-    UpdaterUI ui = new ConsoleUpdaterUI();
+    File tempPatchFile = Utils.createTempFile();
+    createImpl(oldBuildDesc,
+               newBuildDesc,
+               oldFolder,
+               newFolder,
+               patchFile,
+               tempPatchFile,
+               ignoredFiles,
+               criticalFiles,
+               optionalFiles,
+               new ConsoleUpdaterUI(), resolveJarFile());
+  }
+
+  static void createImpl(String oldBuildDesc,
+                         String newBuildDesc,
+                         String oldFolder,
+                         String newFolder,
+                         String outPatchJar,
+                         File   tempPatchFile,
+                         List<String> ignoredFiles,
+                         List<String> criticalFiles,
+                         List<String> optionalFiles,
+                         UpdaterUI ui,
+                         File resolvedJar) throws IOException, OperationCancelledException {
     try {
-      File tempPatchFile = Utils.createTempFile();
       PatchFileCreator.create(new File(oldFolder),
                               new File(newFolder),
                               tempPatchFile,
@@ -138,13 +175,13 @@
                               optionalFiles,
                               ui);
 
-      logger.info("Packing JAR file: " + patchFile );
-      ui.startProcess("Packing JAR file '" + patchFile + "'...");
+      logger.info("Packing JAR file: " + outPatchJar );
+      ui.startProcess("Packing JAR file '" + outPatchJar + "'...");
 
-      FileOutputStream fileOut = new FileOutputStream(patchFile);
+      FileOutputStream fileOut = new FileOutputStream(outPatchJar);
       try {
         ZipOutputWrapper out = new ZipOutputWrapper(fileOut);
-        ZipInputStream in = new ZipInputStream(new FileInputStream(resolveJarFile()));
+        ZipInputStream in = new ZipInputStream(new FileInputStream(resolvedJar));
         try {
           ZipEntry e;
           while ((e = in.getNextEntry()) != null) {
@@ -186,7 +223,7 @@
     Utils.cleanup();
   }
 
-  private static void install(final String destFolder) throws Exception {
+  private static void install(final boolean useExitCode0, final String destFolder) throws Exception {
     InputStream in = Runner.class.getResourceAsStream("/" + PATCH_PROPERTIES_ENTRY);
     Properties props = new Properties();
     try {
@@ -213,7 +250,9 @@
 
     new SwingUpdaterUI(props.getProperty(OLD_BUILD_DESCRIPTION),
                   props.getProperty(NEW_BUILD_DESCRIPTION),
+                  useExitCode0 ? 0 : SwingUpdaterUI.RESULT_REQUIRES_RESTART,
                   new SwingUpdaterUI.InstallOperation() {
+                    @Override
                     public boolean execute(UpdaterUI ui) throws OperationCancelledException {
                       logger.info("installing patch to the " + destFolder);
                       return doInstall(ui, destFolder);
@@ -221,11 +260,26 @@
                   });
   }
 
+  interface IJarResolver {
+    File resolveJar() throws IOException;
+  }
+
   private static boolean doInstall(UpdaterUI ui, String destFolder) throws OperationCancelledException {
+    return doInstallImpl(ui, destFolder, new IJarResolver() {
+      @Override
+      public File resolveJar() throws IOException {
+        return resolveJarFile();
+      }
+    });
+  }
+
+  static boolean doInstallImpl(UpdaterUI ui,
+                               String destFolder,
+                               IJarResolver jarResolver) throws OperationCancelledException {
     try {
       try {
         File patchFile = Utils.createTempFile();
-        ZipFile jarFile = new ZipFile(resolveJarFile());
+        ZipFile jarFile = new ZipFile(jarResolver.resolveJar());
 
         logger.info("Extracting patch file...");
         ui.startProcess("Extracting patch file...");
diff --git a/updater/src/com/intellij/updater/SwingUpdaterUI.java b/updater/src/com/intellij/updater/SwingUpdaterUI.java
old mode 100644
new mode 100755
index d44fc2e..749dcc2
--- a/updater/src/com/intellij/updater/SwingUpdaterUI.java
+++ b/updater/src/com/intellij/updater/SwingUpdaterUI.java
@@ -10,6 +10,7 @@
 import java.awt.event.ActionListener;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.lang.reflect.InvocationTargetException;
@@ -19,7 +20,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 
 public class SwingUpdaterUI implements UpdaterUI {
-  private static final int RESULT_REQUIRES_RESTART = 42;
+  static final int RESULT_REQUIRES_RESTART = 42;
 
   private static final EmptyBorder FRAME_BORDER = new EmptyBorder(8, 8, 8, 8);
   private static final EmptyBorder LABEL_BORDER = new EmptyBorder(0, 0, 5, 0);
@@ -32,6 +33,7 @@
 
   private static final String PROCEED_BUTTON_TITLE = "Proceed";
 
+  private final int mySuccessExitCode;
   private final InstallOperation myOperation;
 
   private final JLabel myProcessTitle;
@@ -40,16 +42,30 @@
   private final JTextArea myConsole;
   private final JPanel myConsolePane;
 
+  private final JButton myRetryButton;
   private final JButton myCancelButton;
 
   private final ConcurrentLinkedQueue<UpdateRequest> myQueue = new ConcurrentLinkedQueue<UpdateRequest>();
   private final AtomicBoolean isCancelled = new AtomicBoolean(false);
   private final AtomicBoolean isRunning = new AtomicBoolean(false);
   private final AtomicBoolean hasError = new AtomicBoolean(false);
+  private final AtomicBoolean hasRetry = new AtomicBoolean(false);
   private final JFrame myFrame;
   private boolean myApplied;
 
-  public SwingUpdaterUI(String oldBuildDesc, String newBuildDesc, InstallOperation operation) {
+  /**
+   * Displays the updater UI and asynchronously runs the operation list.
+   *
+   * @param oldBuildDesc The old build description, for display purposes.
+   * @param newBuildDesc The new build description, for display purposes.
+   * @param successExitCode The desired exit code on success. Default is {@link #RESULT_REQUIRES_RESTART}.
+   * @param operation The install operations to perform.
+   */
+  public SwingUpdaterUI(String oldBuildDesc,
+                        String newBuildDesc,
+                        int successExitCode,
+                        InstallOperation operation) {
+    mySuccessExitCode = successExitCode;
     myOperation = operation;
 
     myProcessTitle = new JLabel(" ");
@@ -58,6 +74,10 @@
 
     myCancelButton = new JButton(CANCEL_BUTTON_TITLE);
 
+    myRetryButton = new JButton("Retry");
+    myRetryButton.setEnabled(false);
+    myRetryButton.setVisible(false);
+
     myConsole = new JTextArea();
     myConsole.setLineWrap(true);
     myConsole.setWrapStyleWord(true);
@@ -70,11 +90,19 @@
     myConsolePane.setVisible(false);
 
     myCancelButton.addActionListener(new ActionListener() {
+      @Override
       public void actionPerformed(ActionEvent e) {
         doCancel();
       }
     });
 
+    myRetryButton.addActionListener(new ActionListener() {
+      @Override
+      public void actionPerformed(ActionEvent e) {
+        doRetry();
+      }
+    });
+
     myFrame = new JFrame();
     myFrame.setTitle(TITLE);
 
@@ -104,6 +132,7 @@
     buttonsPanel.setBorder(BUTTONS_BORDER);
     buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
     buttonsPanel.add(Box.createHorizontalGlue());
+    buttonsPanel.add(myRetryButton);
     buttonsPanel.add(myCancelButton);
 
     myProcessTitle.setText("<html>Updating " + oldBuildDesc + " to " + newBuildDesc + "...");
@@ -129,6 +158,7 @@
 
   private void startRequestDispatching() {
     new Thread(new Runnable() {
+      @Override
       public void run() {
         while (true) {
           try {
@@ -146,6 +176,7 @@
           }
 
           SwingUtilities.invokeLater(new Runnable() {
+            @Override
             public void run() {
               for (UpdateRequest each : pendingRequests) {
                 each.perform();
@@ -172,10 +203,28 @@
     }
   }
 
+  private void doRetry() {
+    hasError.set(false);
+    hasRetry.set(false);
+    isCancelled.set(false);
+    myQueue.add(new UpdateRequest() {
+      @Override
+      public void perform() {
+        myConsole.setText("");
+        myConsolePane.setVisible(false);
+        myConsolePane.setPreferredSize(new Dimension(10, 200));
+        myRetryButton.setEnabled(false);
+        myCancelButton.setEnabled(true);
+      }
+    });
+    doPerform();
+  }
+
   private void doPerform() {
     isRunning.set(true);
 
     new Thread(new Runnable() {
+      @Override
       public void run() {
         try {
           myApplied = myOperation.execute(SwingUpdaterUI.this);
@@ -190,6 +239,10 @@
         finally {
           isRunning.set(false);
 
+          if (hasRetry.get()) {
+            myRetryButton.setVisible(true);
+            myRetryButton.setEnabled(true);
+          }
           if (hasError.get()) {
             startProcess("Failed to apply patch");
             setProgress(100);
@@ -204,15 +257,17 @@
   }
 
   private void exit() {
-    System.exit(myApplied ? RESULT_REQUIRES_RESTART : 0);
+    System.exit(myApplied ? mySuccessExitCode : 0);
   }
 
+  @Override
   public Map<String, ValidationResult.Option> askUser(final List<ValidationResult> validationResults) throws OperationCancelledException {
     if (validationResults.isEmpty()) return Collections.emptyMap();
 
     final Map<String, ValidationResult.Option> result = new HashMap<String, ValidationResult.Option>();
     try {
       SwingUtilities.invokeAndWait(new Runnable() {
+        @Override
         public void run() {
           final JDialog dialog = new JDialog(myFrame, TITLE, true);
           dialog.setLayout(new BorderLayout());
@@ -224,6 +279,7 @@
           buttonsPanel.add(Box.createHorizontalGlue());
           JButton proceedButton = new JButton(PROCEED_BUTTON_TITLE);
           proceedButton.addActionListener(new ActionListener() {
+            @Override
             public void actionPerformed(ActionEvent e) {
               dialog.setVisible(false);
             }
@@ -231,6 +287,7 @@
 
           JButton cancelButton = new JButton(CANCEL_BUTTON_TITLE);
           cancelButton.addActionListener(new ActionListener() {
+            @Override
             public void actionPerformed(ActionEvent e) {
               isCancelled.set(true);
               myCancelButton.setEnabled(false);
@@ -287,8 +344,10 @@
     return result;
   }
 
+  @Override
   public void startProcess(final String title) {
     myQueue.add(new UpdateRequest() {
+      @Override
       public void perform() {
         myProcessStatus.setText(title);
         myProcessProgress.setIndeterminate(false);
@@ -297,8 +356,10 @@
     });
   }
 
+  @Override
   public void setProgress(final int percentage) {
     myQueue.add(new UpdateRequest() {
+      @Override
       public void perform() {
         myProcessProgress.setIndeterminate(false);
         myProcessProgress.setValue(percentage);
@@ -306,21 +367,43 @@
     });
   }
 
+  @Override
   public void setProgressIndeterminate() {
     myQueue.add(new UpdateRequest() {
+      @Override
       public void perform() {
         myProcessProgress.setIndeterminate(true);
       }
     });
   }
 
+  @Override
   public void setStatus(final String status) {
   }
 
+  @Override
   public void showError(final Throwable e) {
     hasError.set(true);
+    StringWriter w = new StringWriter();
+
+    if (e instanceof RetryException) {
+      hasRetry.set(true);
+
+      w.write("+----------------\n");
+      w.write("| A file operation failed.\n");
+      w.write("| This might be due to a file being locked by another\n");
+      w.write("| application. Please try closing any application\n");
+      w.write("| that uses the files being updated then press 'Retry'.\n");
+      w.write("+----------------\n");
+      w.write("\n\n");
+    }
+
+    e.printStackTrace(new PrintWriter(w));
+
+    final String content = w.getBuffer().toString();
 
     myQueue.add(new UpdateRequest() {
+      @Override
       public void perform() {
         StringWriter w = new StringWriter();
         if (!myConsolePane.isVisible()) {
@@ -328,9 +411,8 @@
           w.write(System.getProperty("java.io.tmpdir"));
           w.write("\n\n");
         }
-        e.printStackTrace(new PrintWriter(w));
-        w.append("\n");
         myConsole.append(w.getBuffer().toString());
+        myConsole.append(content);
         if (!myConsolePane.isVisible()) {
           myConsole.setCaretPosition(0);
           myConsolePane.setVisible(true);
@@ -341,6 +423,7 @@
     });
   }
 
+  @Override
   public void checkCancelled() throws OperationCancelledException {
     if (isCancelled.get()) throw new OperationCancelledException();
   }
@@ -354,7 +437,8 @@
   }
 
   public static void main(String[] args) {
-    new SwingUpdaterUI("xxx", "yyy", new InstallOperation() {
+    new SwingUpdaterUI("xxx", "yyy", RESULT_REQUIRES_RESTART, new InstallOperation() {
+      @Override
       public boolean execute(UpdaterUI ui) throws OperationCancelledException {
         ui.startProcess("Process1");
         ui.checkCancelled();
@@ -438,6 +522,7 @@
       }
     }
 
+    @Override
     public int getColumnCount() {
       return COLUMNS.length;
     }
@@ -464,6 +549,7 @@
       return super.getColumnClass(columnIndex);
     }
 
+    @Override
     public int getRowCount() {
       return myItems.size();
     }
@@ -480,6 +566,7 @@
       }
     }
 
+    @Override
     public Object getValueAt(int rowIndex, int columnIndex) {
       Item item = myItems.get(rowIndex);
       switch (columnIndex) {
diff --git a/updater/src/com/intellij/updater/Utils.java b/updater/src/com/intellij/updater/Utils.java
old mode 100644
new mode 100755
index 959a93c..b5ad212
--- a/updater/src/com/intellij/updater/Utils.java
+++ b/updater/src/com/intellij/updater/Utils.java
@@ -10,10 +10,19 @@
   private static final byte[] BUFFER = new byte[64 * 1024];
   private static File myTempDir;
 
+  public static boolean isWindows() {
+    return System.getProperty("os.name").startsWith("Windows");
+  }
+
   public static boolean isZipFile(String fileName) {
     return fileName.endsWith(".zip") || fileName.endsWith(".jar");
   }
 
+  /**
+   * Creates a new temp file. <br/>
+   * All the temp files created here are located in a unique root temp directory
+   * that is automatically deleted by {@link #cleanup()}.
+   */
   @SuppressWarnings({"SSBasedInspection"})
   public static File createTempFile() throws IOException {
     if (myTempDir == null) {
@@ -26,6 +35,12 @@
     return File.createTempFile("temp.", ".tmp", myTempDir);
   }
 
+
+  /**
+   * Creates a new temp directory. <br/>
+   * All the temp directories created here are located in a unique root temp directory
+   * that is automatically deleted by {@link #cleanup()}.
+   */
   public static File createTempDir() throws IOException {
     File result = createTempFile();
     delete(result);
@@ -42,6 +57,15 @@
     myTempDir = null;
   }
 
+  /**
+   * Deletes a file or directory with a default timeout of 100 milliseconds.
+   * Directories are deleted recursively. The timeout occurs on each file.
+   * If one of the files fails to be deleted, the recursive directory deletion
+   * is aborted and not retried.
+   *
+   * @param file The file or directory to delete.
+   * @throws IOException
+   */
   public static void delete(File file) throws IOException {
     if (file.isDirectory()) {
       File[] files = file.listFiles();
@@ -52,16 +76,20 @@
         }
       }
     }
+
     for (int i = 0; i < 10; i++) {
-      if (file.delete() || !file.exists()) return;
+      if (file.delete() || !file.exists()) {
+        return;
+      }
       try {
         Thread.sleep(10);
-      }
-      catch (InterruptedException ignore) {
+      } catch (InterruptedException ignore) {
         Runner.printStackTrace(ignore);
       }
     }
-    if (file.exists()) throw new IOException("Cannot delete file " + file);
+    if (file.exists()) {
+      throw new IOException("Cannot delete file " + file);
+    }
   }
 
   public static void setExecutable(File file, boolean executable) throws IOException {
diff --git a/updater/testSrc/com/intellij/updater/RunnerAdditionalTest.java b/updater/testSrc/com/intellij/updater/RunnerAdditionalTest.java
new file mode 100644
index 0000000..577c2bc
--- /dev/null
+++ b/updater/testSrc/com/intellij/updater/RunnerAdditionalTest.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2014 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.intellij.updater;
+
+import junit.framework.TestCase;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.util.*;
+
+public class RunnerAdditionalTest extends TestCase {
+  private final LinkedList<File> myFiles = new LinkedList<File>();
+  private final ArrayList<NamePair> myFileNames = new ArrayList<NamePair>();
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    myFiles.clear();
+    myFileNames.clear();
+  }
+
+  @Override
+  public void tearDown() throws Exception {
+    super.tearDown();
+
+    while (!myFiles.isEmpty()) {
+      remove(myFiles.removeLast());
+    }
+  }
+
+  public void testUpdater1() throws Exception {
+    File dir1 = add(createTempDir("old", ".dir"));
+    File dir2 = add(createTempDir("new", ".dir"));
+    File f3 = add(createFileContent(dir1, "something.txt", "Content version 1"));
+    File f4 = add(createFileContent(dir2, "something.txt", "Content version 2"));
+    File inputJar5 = add(File.createTempFile("input", ".jar"));
+    File tmpPatch6 = add(File.createTempFile("temp", ".patch"));
+    final File patch7 = add(File.createTempFile("output", ".jar"));
+
+    createEmptyJar(inputJar5);
+
+    //noinspection ResultOfMethodCallIgnored
+    patch7.delete();
+    assertFalse(patch7.exists());
+
+    MockUpdaterUI ui1 = new MockUpdaterUI();
+    Runner.createImpl("1.2",                    //oldBuildDesc
+                      "1.3",                    //newBuildDesc
+                      dir1.getAbsolutePath(),   //oldFolder
+                      dir2.getAbsolutePath(),   //newFolder
+                      patch7.getAbsolutePath(), //outPatchJar
+                      tmpPatch6,                //tempPatchFile
+                      new ArrayList<String>(),  //ignoredFiles
+                      new ArrayList<String>(),  //criticalFiles
+                      new ArrayList<String>(),  //optionalFiles
+                      ui1,                      //ui
+                      inputJar5);               //resolvedJar
+
+    assertEquals(
+      "[Start   ] Calculating difference...\n" +
+      "[Status  ] something.txt\n" +
+      "[Status  ] something.txt\n" +
+      "[Start   ] Preparing actions...\n" +
+      "[Status  ] something.txt\n" +
+      "[Start   ] Creating the patch file 'file-6_temp.patch'...\n" +
+      "[Status  ] Packing something.txt\n" +
+      "[Start   ] Packing jar file 'file-7_output.jar'...\n" +
+      "[Start   ] Cleaning up...\n" +
+      "[Indeterminate Progress]\n",
+      ui1.toString());
+    assertTrue(patch7.exists());
+
+    File dir8 = add(createTempDir("extracted", ".dir"));
+    File f9 = add(createFileContent(dir8, "something.txt", "Content version 1"));
+    assertTrue(f9.exists());
+
+    MockUpdaterUI ui2 = new MockUpdaterUI();
+    Runner.doInstallImpl(ui2,
+                         dir8.getAbsolutePath(),
+                         new Runner.IJarResolver() {
+                           @Override
+                           public File resolveJar() throws IOException {
+                             return patch7;
+                           }
+                         });
+    assertEquals(
+      "[Start   ] Extracting patch file...\n" +
+      "[Indeterminate Progress]\n" +
+      "[Start   ] Validating installation...\n" +
+      "[Status  ] something.txt\n" +
+      "[Progress] 100\n" +
+      "[Start   ] Backing up files...\n" +
+      "[Status  ] something.txt\n" +
+      "[Progress] 100\n" +
+      "[Start   ] Applying patch...\n" +
+      "[Status  ] something.txt\n" +
+      "[Progress] 100\n" +
+      "[Start   ] Cleaning up...\n" +
+      "[Indeterminate Progress]\n",
+      ui2.toString());
+    assertEquals("Content version 2", getFileContent(f9));
+  }
+
+  //---- utilities -----
+
+  private File createTempDir(String prefix, String suffix) throws IOException {
+    File d = File.createTempFile(prefix, suffix);
+    if (!d.delete()) throw new IOException("Failed to delete directory " + d.getAbsolutePath());
+    if (!d.mkdirs()) throw new IOException("Failed to mkdirs " + d.getAbsolutePath());
+    return d;
+  }
+
+  private static void createEmptyJar(File jar) throws IOException {
+    FileOutputStream outStream = new FileOutputStream(jar);
+    try {
+      ZipOutputWrapper out = new ZipOutputWrapper(outStream);
+
+      // zip file can't be empty, add one dummy entry
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      baos.write("dummy entry".getBytes("UTF-8"));
+      out.zipBytes("dummy.txt", baos);
+
+      out.finish();
+    } finally {
+      outStream.close();
+    }
+  }
+
+  private File add(File f) {
+    myFiles.add(f);
+
+    String unique = f.getName().replaceAll("[^a-zA-Z.]", "");
+    NamePair fromTo = new NamePair(f.getAbsolutePath(),
+                                   (f.isDirectory() ? "dir-" : "file-") + (myFileNames.size() + 1) + '_' + unique);
+    myFileNames.add(fromTo);
+    Collections.sort(myFileNames);
+    return f;
+  }
+
+  private String getFileContent(File file) throws IOException {
+    if (!file.exists()) throw new IOException("File not found, expected file: " + replaceFileNames(file.getAbsolutePath()));
+    BufferedReader br = new BufferedReader(new FileReader(file));
+    try {
+      return br.readLine();
+    } finally {
+      br.close();
+    }
+  }
+
+  private static File createFileContent(File parentDir, String fileName, String fileContent) throws IOException {
+    File f = new File(parentDir, fileName);
+    OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(f), Charset.forName("UTF-8"));
+    try {
+      fw.write(fileContent);
+    } finally {
+      fw.close();
+    }
+    return f;
+  }
+
+  private static void remove(File... files) {
+    for (File f : files) {
+      if (f != null && f.exists()) {
+        if (!f.delete()) {
+          f.deleteOnExit();
+        }
+      }
+    }
+  }
+
+  private String replaceFileNames(String str) {
+    for (NamePair name : myFileNames) {
+      str = str.replace(name.getFrom(), name.getTo());
+    }
+    return str;
+  }
+
+  /**
+   * A list of from->to name pairs, ordered by descending from
+   * (to get the longer ones first.)
+   */
+  private static class NamePair implements Comparable<NamePair> {
+    private final String myFrom;
+    private final String myTo;
+
+    public NamePair(String from, String to) {
+      myFrom = from;
+      myTo = to;
+    }
+
+    public String getFrom() {
+      return myFrom;
+    }
+
+    public String getTo() {
+      return myTo;
+    }
+
+    @Override
+    public int compareTo(NamePair n2) {
+      return -1 * this.getFrom().compareTo(n2.getFrom());
+    }
+  }
+
+  /**
+   * Mock UpdaterUI that dumps all the text to a string buffer, which can be
+   * grabbed using toString(). It also replaces all the filenames using the
+   * provided name pair list.
+   */
+  private class MockUpdaterUI implements UpdaterUI {
+    private final StringBuilder myOutput = new StringBuilder();
+
+    private MockUpdaterUI() {
+    }
+
+    @Override
+    public void startProcess(String title) {
+      title = replaceFileNames(title);
+      myOutput.append("[Start   ] ").append(title).append('\n');
+    }
+
+    @Override
+    public void setProgress(int percentage) {
+      myOutput.append("[Progress] ").append(percentage).append('\n');
+    }
+
+    @Override
+    public void setProgressIndeterminate() {
+      myOutput.append("[Indeterminate Progress]\n");
+    }
+
+    @Override
+    public void setStatus(String status) {
+      status = replaceFileNames(status);
+      myOutput.append("[Status  ] ").append(status).append('\n');
+    }
+
+    @Override
+    public void showError(Throwable e) {
+      myOutput.append("[Error   ] ").append(e.toString()).append('\n');
+    }
+
+    @Override
+    public void checkCancelled() throws OperationCancelledException {
+      // no-op
+    }
+
+    @Override
+    public Map<String, ValidationResult.Option> askUser(List<ValidationResult> validationResults) throws OperationCancelledException {
+      return Collections.emptyMap();
+    }
+
+    @Override
+    public String toString() {
+      return myOutput.toString();
+    }
+  }
+}
diff --git a/updater/testSrc/com/intellij/updater/UtilsTest.java b/updater/testSrc/com/intellij/updater/UtilsTest.java
new file mode 100755
index 0000000..6e9e4eb
--- /dev/null
+++ b/updater/testSrc/com/intellij/updater/UtilsTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.updater;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class UtilsTest extends TestCase {
+
+  private boolean mIsWindows;
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    mIsWindows = Utils.isWindows();
+  }
+
+  public void testDelete() throws Exception {
+    File f = File.createTempFile("test", "tmp");
+    assertTrue(f.exists());
+
+    try {
+      Utils.delete(f);
+      assertFalse(f.exists());
+    } finally {
+      f.deleteOnExit();
+    }
+  }
+
+  public void testDelete_LockedFile() throws Exception {
+    File f = File.createTempFile("test", "tmp");
+    assertTrue(f.exists());
+
+    long millis = 0;
+    FileWriter fw = new FileWriter(f);
+    try {
+      // This locks the file on Windows, preventing it from being deleted.
+      // Utils.delete() will retry for about 100 ms.
+      fw.write("test");
+      millis = System.currentTimeMillis();
+
+      Utils.delete(f);
+
+    } catch (IOException e) {
+      millis = System.currentTimeMillis() - millis;
+      assertEquals("Cannot delete file " + f.getAbsolutePath(), e.getMessage());
+      assertTrue("Utils.delete took " + millis + " ms, which is less than the expected 100 ms.", millis > 100);
+      return;
+
+    } finally {
+      f.deleteOnExit();
+      fw.close();
+    }
+
+    assertFalse("Utils.delete did not fail with the expected IOException on Windows.", mIsWindows);
+  }
+}
diff --git a/updater/testUI/.gitignore b/updater/testUI/.gitignore
new file mode 100644
index 0000000..378eac2
--- /dev/null
+++ b/updater/testUI/.gitignore
@@ -0,0 +1 @@
+build
diff --git a/updater/testUI/build.gradle b/updater/testUI/build.gradle
new file mode 100755
index 0000000..2c86712
--- /dev/null
+++ b/updater/testUI/build.gradle
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.nio.charset.Charset
+
+apply plugin: "application"
+
+project.mainClassName = "com.intellij.updater.Runner"
+
+defaultTasks "testSuite"
+
+repositories {
+  mavenCentral()
+}
+
+dependencies {
+  compile files("../../lib/log4j.jar")
+  testCompile group: "junit", name: "junit", version: "3.+"
+}
+
+sourceSets {
+  main {
+    java      { srcDir "../src" }
+    resources { srcDir "../src" }
+  }
+  test {
+    java      { srcDir "../tests" }
+    resources { srcDir "../tests" }
+  }
+}
+
+
+test {
+  testLogging {
+    showStandardStreams = true
+    showStackTraces = true
+    exceptionFormat = "full"
+  }
+}
+
+//---
+
+// Task : Tests updater create + install in the default normal case.
+// Scope: large test.
+// Running this will display the install patcher UI.
+task testUI1(dependsOn: jar) << {
+  println "## Running UI test 1"
+  println "## Jar file: " + jar.archivePath.getAbsolutePath()
+
+  // Create a temp dir inside the gradle build/tmp dir
+  //noinspection GroovyAssignabilityCheck
+  def buildTmpDir = new File(project.buildDir, "tmp");
+  def tmpDir = _createTempDir(buildTmpDir)
+  def logDir = _createTempDir(buildTmpDir)
+
+  try {
+    // create a "from version 1" and "to version 2" directories
+    def dataDir1 = _createTestData(tmpDir, "1")
+    assert  _mkFile(dataDir1, "plugins", "v1", "myplugin.jar").exists()
+    assert !_mkFile(dataDir1, "plugins", "v2", "myplugin.jar").exists()
+    assert _getFileContent(_mkFile(dataDir1, "build.txt")).equals("AI-123.45678-1")
+
+    def dataDir2 = _createTestData(tmpDir, "2")
+    assert !_mkFile(dataDir2, "plugins", "v1", "myplugin.jar").exists()
+    assert  _mkFile(dataDir2, "plugins", "v2", "myplugin.jar").exists()
+    assert _getFileContent(_mkFile(dataDir2, "build.txt")).equals("AI-123.45678-2")
+
+    def patch    = _createFileContent(tmpDir, "patch.jar", "patch jar placeholder");
+    patch.delete()
+    assert !patch.exists()
+
+    def logFullFile  = _mkFile(logDir, "idea_updater.log")
+    def logErrorFile = _mkFile(logDir, "idea_updater_error.log")
+    assert !logFullFile .exists()
+    assert !logErrorFile.exists()
+
+    // call updater jar to create a diff, resulting in a patch jar.
+    println "## Invoking updater <create>"
+    javaexec {
+      classpath jar.archivePath
+      classpath "../../lib/log4j.jar"
+      main = "com.intellij.updater.Runner"
+      args "create"
+      args "AI-123.45678-1"
+      args "AI-123.45678-2"
+      args dataDir1.getAbsolutePath()
+      args dataDir2.getAbsolutePath()
+      args patch.getAbsolutePath()
+      args logDir.getAbsolutePath()
+    }
+    assert patch.exists()
+
+    assert logFullFile .exists()
+    assert logErrorFile.exists()    // should exist and be empty
+    assert _getFileContent(logErrorFile).equals(null)
+
+
+    // that patch jar is self-executable. use it to update dir1 into dir2 in-place.
+    println "## Invoking updater <install>"
+    javaexec {
+      classpath patch
+      classpath "../../lib/log4j.jar"
+      main = "com.intellij.updater.Runner"
+      args "install"
+      args "--exit0"
+      args dataDir1.getAbsolutePath()
+      args logDir.getAbsolutePath()
+    }
+    // build.txt should have changed to v2
+    assert _getFileContent(_mkFile(dataDir1, "build.txt")).equals("AI-123.45678-2")
+    // plugin v1 should have been replaced by pluging v2 in the dataDir1 directory.
+    assert !_mkFile(dataDir1, "plugins", "v1", "myplugin.jar").exists()
+    assert  _mkFile(dataDir1, "plugins", "v2", "myplugin.jar").exists()
+
+    assert logFullFile .exists()
+    assert logErrorFile.exists()    // should exist and be empty
+    assert _getFileContent(logErrorFile).equals(null)
+
+  } finally {
+    // Cleanup on exit
+    tmpDir.deleteDir()
+    logDir.deleteDir()
+  }
+}
+
+// Task : Tests updater create + install with 2 open files.
+// Scope: large *interactive* test.
+// On Windows, the opened files are locked and can't be deleted/overwritten.
+// On Linux/Mac, they should be writable & deletable.
+//
+// Running this will display the install patcher UI, which will fail at
+// first on Windows. After 5 seconds the open files will be closed.
+// Hitting "retry" in the UI after this point should perform the whole
+// install operation again.
+task testUI2(dependsOn: jar) << {
+  println "## Running UI test 2"
+  println "## Jar file: " + jar.archivePath.getAbsolutePath()
+
+  // Create a temp dir inside the gradle build/tmp dir
+  //noinspection GroovyAssignabilityCheck
+  def buildTmpDir = new File(project.buildDir, "tmp");
+  def tmpDir = _createTempDir(buildTmpDir)
+  def logDir = _createTempDir(buildTmpDir)
+  def closeableFiles = []
+
+  try {
+    // create a "from version 1" and "to version 2" directories
+    def dataDir1 = _createTestData(tmpDir, "1")
+    assert  _mkFile(dataDir1, "plugins", "v1", "myplugin.jar").exists()
+    assert !_mkFile(dataDir1, "plugins", "v2", "myplugin.jar").exists()
+    assert _getFileContent(_mkFile(dataDir1, "build.txt")).equals("AI-123.45678-1")
+
+    def dataDir2 = _createTestData(tmpDir, "2")
+    assert !_mkFile(dataDir2, "plugins", "v1", "myplugin.jar").exists()
+    assert  _mkFile(dataDir2, "plugins", "v2", "myplugin.jar").exists()
+    assert _getFileContent(_mkFile(dataDir2, "build.txt")).equals("AI-123.45678-2")
+
+    def patch    = _createFileContent(tmpDir, "patch.jar", "patch jar placeholder");
+    patch.delete()
+    assert !patch.exists()
+
+    def logFullFile  = _mkFile(logDir, "idea_updater.log")
+    def logErrorFile = _mkFile(logDir, "idea_updater_error.log")
+    assert !logFullFile .exists()
+    assert !logErrorFile.exists()
+
+    // keep a couple files open, preventing them from being deleted or replaced on Windows
+    closeableFiles << _openFile(_mkFile(dataDir1, "build.txt"))
+    closeableFiles << _openFile(_mkFile(dataDir1, "plugins", "v1", "myplugin.jar"))
+
+    // call updater jar to create a diff, resulting in a patch jar.
+    println "## Invoking updater <create>"
+    javaexec {
+      classpath jar.archivePath
+      classpath "../../lib/log4j.jar"
+      main = "com.intellij.updater.Runner"
+      args "create"
+      args "AI-123.45678-1"
+      args "AI-123.45678-2"
+      args dataDir1.getAbsolutePath()
+      args dataDir2.getAbsolutePath()
+      args patch.getAbsolutePath()
+      args logDir.getAbsolutePath()
+    }
+    assert patch.exists()
+
+    assert logFullFile .exists()
+    assert logErrorFile.exists()    // should exist and be empty
+    assert _getFileContent(logErrorFile).equals(null)
+
+    Thread.start {
+      sleep(5 * 1000) // 5 seconds
+      synchronized(closeableFiles) {
+        println "##"
+        println "## Closing pending open files --> now click 'Retry' in Updater UI."
+        println "##"
+        closeableFiles.each { it.close() }
+        closeableFiles.clear()
+      }
+    }
+
+    // that patch jar is self-executable. use it to update dir1 into dir2 in-place.
+    println "## Invoking updater <install>"
+    println "##"
+    println "## Note: on Windows some files will be locked for 5 seconds and the installer"
+    println "##       window should display a 'Retry' button. This code will wait 5 seconds"
+    println "##       then unlock the files, at which point you would click that 'Retry'"
+    println "##       button and the install should continue correctly."
+    println "##"
+
+    javaexec {
+      classpath patch
+      classpath "../../lib/log4j.jar"
+      main = "com.intellij.updater.Runner"
+      args "install"
+      args "--exit0"
+      args dataDir1.getAbsolutePath()
+      args logDir.getAbsolutePath()
+    }
+    // build.txt should have changed to v2
+    assert _getFileContent(_mkFile(dataDir1, "build.txt")).equals("AI-123.45678-2")
+    // plugin v1 should have been replaced by pluging v2 in the dataDir1 directory.
+    assert !_mkFile(dataDir1, "plugins", "v1", "myplugin.jar").exists()
+    assert  _mkFile(dataDir1, "plugins", "v2", "myplugin.jar").exists()
+
+    assert logFullFile .exists()
+    // the log error file should exist and should not be empty on Windows.
+    assert logErrorFile.exists()
+    if (System.getProperty("os.name").startsWith("Windows")) {
+      assert _getFileContent(logErrorFile) != null
+    } else {
+      assert _getFileContent(logErrorFile).equals(null)
+    }
+
+  } finally {
+    // Cleanup on exit
+    synchronized(closeableFiles) {
+      closeableFiles.each { it.close() }
+      closeableFiles.clear()
+    }
+    tmpDir.deleteDir()
+    logDir.deleteDir()
+  }
+}
+
+// Task: Test suite to run both tests above.
+task testSuite(dependsOn: [testUI1, testUI2]) << {
+}
+
+// ---- Helper methods
+
+// Convention: all local helper methods start with an underscore to clearly
+// differentiate them from groovy/gradle methods.
+
+
+// Creates a temp dir with a random name in the build/tmp directory.
+File _createTempDir(File parent) {
+  def d = File.createTempFile("test", "", parent)
+  d.delete()
+  d.mkdirs()
+  return d
+}
+
+// Creates a new directory with the specific name in the specified parent directory.
+File _createDir(File parent, String name) {
+  def d = new File(parent, name)
+  d.mkdirs()
+  return d
+}
+
+// Creates a new file with the specified name, in the specified parent directory with the given UTF-8 content.
+File _createFileContent(File parentDir, String fileName, String fileContent) throws IOException {
+  File f = new File(parentDir, fileName)
+  OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(f), Charset.forName("UTF-8"))
+  try {
+    fw.write(fileContent)
+  } finally {
+    fw.close()
+  }
+  return f
+}
+
+// Opens a file for writing (thus locking it on Windows) but does not close it.
+// Caller should call Closeable.close() on the returned Closeable object.
+Closeable _openFile(File file) throws IOException {
+  if (!file.exists()) throw new IOException("File not found, expected file: " + file.getName())
+  // We need to actually write to the file but not change its content so just read it
+  // then write the same thing back to it, without closing it.
+  String content = _getFileContent(file)
+  FileWriter fw = new FileWriter(file, false /*append*/)
+  fw.append(content)
+  fw.flush()
+  println("## Open file " + file.getName());
+  return fw   // file is not closed
+}
+
+// Returns the first line of the file.
+// Returns null if the file exists and is empty.
+// Throws IOException if file does not exist.
+String _getFileContent(File file) throws IOException {
+  if (!file.exists()) throw new IOException("File not found, expected file: " + file.getName())
+  BufferedReader br = new BufferedReader(new FileReader(file))
+  try {
+    return br.readLine()
+  } finally {
+    br.close()
+  }
+}
+
+// Creates a new File() object with the concatenated name segments.
+File _mkFile(File base, String...segments) {
+  for(String segment : segments) {
+    base = new File(base, segment)
+  }
+  return base
+}
+
+// Creates a mock test data for an idea-based IDE.
+File _createTestData(File tmpDir, String value) {
+  File root     = _createDir(tmpDir,  "idea-ide-" + value)
+  File bin      = _createDir(root,    "bin")
+  File lib      = _createDir(root,    "lib")
+  File plugins  = _createDir(root,    "plugins")
+  File myplugin = _createDir(plugins, "v" + value)
+
+  _createFileContent(root,     "build.txt",    "AI-123.45678-"  + value);
+  _createFileContent(bin,      "idea.exe",     "binary file "   + value);
+  _createFileContent(lib,      "idea.jar",     "some jar file " + value);
+  _createFileContent(myplugin, "myplugin.jar", "some jar file " + value);
+
+  return root
+}
diff --git a/updater/testUI/gradle/wrapper/gradle-wrapper.jar b/updater/testUI/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..7b359d7
--- /dev/null
+++ b/updater/testUI/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/updater/testUI/gradle/wrapper/gradle-wrapper.properties b/updater/testUI/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..97f4761
--- /dev/null
+++ b/updater/testUI/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Dec 12 15:16:42 PST 2012
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=../../../../../external/gradle/gradle-1.9-bin.zip
diff --git a/updater/testUI/gradlew b/updater/testUI/gradlew
new file mode 100755
index 0000000..779e68d
--- /dev/null
+++ b/updater/testUI/gradlew
@@ -0,0 +1,179 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/"
+APP_HOME="`pwd -P`"
+cd "$SAVED"
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+# Change the project's .gradle to the android out dir.
+ANDROID_GRADLE_ROOT="$APP_HOME/../../../../out/host/gradle/tools/updater"
+if [[ -z "$ANDROID_CACHE_DIR" ]]; then
+  ANDROID_CACHE_DIR="$ANDROID_GRADLE_ROOT/.gradle"
+fi
+
+# Change the local user directories to be under the android out dir
+export GRADLE_USER_HOME="$ANDROID_GRADLE_ROOT/.gradle"
+export M2_HOME="$ANDROID_GRADLE_ROOT/.m2"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" \
+    -classpath "$CLASSPATH" \
+    org.gradle.wrapper.GradleWrapperMain \
+    --project-cache-dir=$ANDROID_CACHE_DIR \
+    "$@"
+
diff --git a/updater/testUI/gradlew.bat b/updater/testUI/gradlew.bat
new file mode 100755
index 0000000..3569a7b
--- /dev/null
+++ b/updater/testUI/gradlew.bat
@@ -0,0 +1,96 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Change the project's .gradle to the android out dir.
+set ANDROID_GRADLE_ROOT=%APP_HOME%\..\..\..\..\out\host\gradle\tools\updater
+set ANDROID_CACHE_DIR=%ANDROID_GRADLE_ROOT%\.gradle
+set GRADLE_USER_HOME=%ANDROID_GRADLE_ROOT%\.gradle
+set M2_HOME=%ANDROID_GRADLE_ROOT%\.m2
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% --project-cache-dir=%ANDROID_CACHE_DIR%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/updater/updater.iml b/updater/updater.iml
old mode 100644
new mode 100755