ruboto 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -181,6 +181,12 @@ def remove_unneeded_parts_of_stdlib
181
181
  end
182
182
  end
183
183
 
184
+ def add_fake_jar(source_file, jar_load_code)
185
+ File.write(source_file, jar_load_code)
186
+ open("#{File.dirname(source_file)}/.jrubydir", 'a') { |f| f.puts File.basename source_file }
187
+ end
188
+ private :add_fake_jar
189
+
184
190
  def cleanup_jars
185
191
  Dir.chdir 'new' do
186
192
  cmd_line_jar_found = false
@@ -224,6 +230,7 @@ def cleanup_jars
224
230
  print "#{File.basename(j).chomp('.jar')}..."
225
231
  system "jar xf #{j}"
226
232
  FileUtils.rm j
233
+
227
234
  if ENV['STRIP_INVOKERS']
228
235
  invokers = Dir['**/*$INVOKER$*.class']
229
236
  if invokers.size > 0
@@ -252,6 +259,22 @@ def cleanup_jars
252
259
  Java::json.ext.ParserService.new.basicLoad(JRuby.runtime)
253
260
  END_CODE
254
261
  elsif j =~ %r{jopenssl.jar$}
262
+ # FIXME(uwe): Use our own patched version of OpenSSL until jruby-openssl 0.9.16 is released
263
+ # FIXME(uwe): Remove before Ruboto release!
264
+ # FIXME(uwe): Remove after jruby-openssl 0.9.16 is added to the jruby-1_7 branch
265
+ if File.exists? 'org/jruby/ext/openssl/OpenSSL.class'
266
+ puts '*' * 80
267
+ puts 'Patching OpenSSL'
268
+ FileUtils.rm 'org/jruby/ext/openssl/OpenSSL.class'
269
+ FileUtils.mkdir_p '../../../src/org/jruby/ext/openssl'
270
+ # require 'ruboto'
271
+ # FileUtils.cp "#{Ruboto::ASSETS}/src/org/jruby/ext/openssl/OpenSSL.java",
272
+ # '../../../src/org/jruby/ext/openssl/OpenSSL.java'
273
+ FileUtils.cp File.expand_path('../../../assets/src/org/jruby/ext/openssl/OpenSSL.java', File.dirname(__FILE__)),
274
+ '../../../src/org/jruby/ext/openssl/OpenSSL.java'
275
+ puts '*' * 80
276
+ end
277
+ # EMXIF
255
278
  jar_load_code = <<-END_CODE
256
279
  require 'jruby'
257
280
  puts 'Starting JOpenSSL Service'
@@ -279,10 +302,11 @@ def cleanup_jars
279
302
  END_CODE
280
303
  else
281
304
  jar_load_code = ''
305
+ add_fake_jar("#{j}", jar_load_code)
282
306
  end
283
307
 
284
- File.open("#{j}.rb", 'w') { |f| f << jar_load_code }
285
- File.open("#{j}.jar.rb", 'w') { |f| f << jar_load_code }
308
+ add_fake_jar("#{j}.rb", jar_load_code)
309
+ # add_fake_jar("#{j}.jar.rb", jar_load_code)
286
310
  end
287
311
  unless cmd_line_jar_found
288
312
  puts "\nWARNING: No command line jar filtered. Has it changed?"
@@ -1,10 +1,40 @@
1
+ ###################################
2
+ #
3
+ # emulator:
4
+ #
5
+ # Specifies which emulator to use when running `ruboto emulator`.
6
+ #
7
+ # Name of the AVD to be used. It will be created if not already present.
8
+ # default: "Android_#{android_version}"
9
+ #
10
+ # name: Android_4.0.3_tablet
11
+ #
12
+ # Name of the Android device to be used as template. Setting this options
13
+ # disables the "skin" option on AVD creation and starts the emulator without
14
+ # the "-no-skin" option.
15
+ # default: Nexus One
16
+ #
17
+ # device: Nexus 10
18
+ #
19
+ # Name of the Android emulator skin to use when creating the AVD.
20
+ # default: HVGA
21
+ #
22
+ # skin: HVGA
23
+ #
24
+ # Example:
25
+ #
26
+ # emulator:
27
+ # name: Android_4.0.3_tablet # default: "Android_#{android_version}"
28
+ # device: Nexus 10 # default: Nexus One
29
+ # skin: HVGA # default: HVGA
30
+
1
31
  ###################################
2
32
  #
3
33
  # heap_alloc
4
- #
34
+ #
5
35
  # Forces the heap to grow by a number of megabytes.
6
36
  # Can result in improved start-up performance because
7
- # it prevents the heap from growing through smaller
37
+ # it prevents the heap from growing through smaller
8
38
  # increments.
9
39
  #
10
40
  # heap_alloc: 13
@@ -0,0 +1,320 @@
1
+ /*
2
+ * The MIT License
3
+ *
4
+ * Copyright (c) 2014 Karol Bucek LTD.
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ */
24
+ package org.jruby.ext.openssl;
25
+
26
+ import java.security.NoSuchProviderException;
27
+ import java.util.Map;
28
+
29
+ import org.jruby.CompatVersion;
30
+ import org.jruby.Ruby;
31
+ import org.jruby.RubyArray;
32
+ import org.jruby.RubyClass;
33
+ import org.jruby.RubyModule;
34
+ import org.jruby.RubyString;
35
+ import org.jruby.anno.JRubyMethod;
36
+ import org.jruby.anno.JRubyModule;
37
+ import org.jruby.runtime.ThreadContext;
38
+ import org.jruby.runtime.builtin.IRubyObject;
39
+ import org.jruby.util.ByteList;
40
+ import org.jruby.util.SafePropertyAccessor;
41
+
42
+ /**
43
+ * OpenSSL (methods as well as an entry point)
44
+ *
45
+ * @author kares
46
+ */
47
+ @JRubyModule(name = "OpenSSL")
48
+ public final class OpenSSL {
49
+
50
+ public static void load(final Ruby runtime) {
51
+ System.out.println("CUSTOM OpenSSL load");
52
+ createOpenSSL(runtime);
53
+ }
54
+
55
+ public static boolean isProviderAvailable() {
56
+ System.out.println("CUSTOM OpenSSL isProviderAvailable");
57
+ return SecurityHelper.isProviderAvailable("BC");
58
+ }
59
+
60
+ public static void createOpenSSL(final Ruby runtime) {
61
+ System.out.println("CUSTOM OpenSSL createOpenSSL");
62
+ boolean registerProvider = SafePropertyAccessor.getBoolean("jruby.openssl.provider.register");
63
+ SecurityHelper.setRegisterProvider( registerProvider );
64
+
65
+ System.out.println("OpenSSL createOpenSSL create module");
66
+ final RubyModule _OpenSSL = runtime.getOrCreateModule("OpenSSL");
67
+ System.out.println("OpenSSL createOpenSSL create OpenSSLError");
68
+ RubyClass _StandardError = runtime.getClass("StandardError");
69
+ _OpenSSL.defineClassUnder("OpenSSLError", _StandardError, _StandardError.getAllocator());
70
+ System.out.println("OpenSSL createOpenSSL defineAnnotatedMethods");
71
+ _OpenSSL.defineAnnotatedMethods(OpenSSL.class);
72
+
73
+ // set OpenSSL debug internal flag early on so it can print traces even while loading extension
74
+ System.out.println("OpenSSL createOpenSSL debug");
75
+ setDebug(_OpenSSL, runtime.newBoolean( SafePropertyAccessor.getBoolean("jruby.openssl.debug") ) );
76
+
77
+ System.out.println("OpenSSL createOpenSSL warn");
78
+ final String warn = SafePropertyAccessor.getProperty("jruby.openssl.warn");
79
+ if ( warn != null ) OpenSSL.warn = Boolean.parseBoolean(warn);
80
+
81
+ System.out.println("OpenSSL createOpenSSL createPKey");
82
+ PKey.createPKey(runtime, _OpenSSL);
83
+ System.out.println("OpenSSL createOpenSSL createBN");
84
+ BN.createBN(runtime, _OpenSSL);
85
+ System.out.println("OpenSSL createOpenSSL createDigest");
86
+ Digest.createDigest(runtime, _OpenSSL);
87
+ System.out.println("OpenSSL createOpenSSL createCipher");
88
+ Cipher.createCipher(runtime, _OpenSSL);
89
+ System.out.println("OpenSSL createOpenSSL createRandom");
90
+ Random.createRandom(runtime, _OpenSSL);
91
+ System.out.println("OpenSSL createOpenSSL createHMAC");
92
+ HMAC.createHMAC(runtime, _OpenSSL);
93
+ System.out.println("OpenSSL createOpenSSL createConfig");
94
+ Config.createConfig(runtime, _OpenSSL);
95
+ System.out.println("OpenSSL createOpenSSL createASN1");
96
+ ASN1.createASN1(runtime, _OpenSSL);
97
+ System.out.println("OpenSSL createOpenSSL createX509");
98
+ X509.createX509(runtime, _OpenSSL);
99
+ System.out.println("OpenSSL createOpenSSL createNetscapeSPKI");
100
+ NetscapeSPKI.createNetscapeSPKI(runtime, _OpenSSL);
101
+ try {
102
+ System.out.println("OpenSSL createOpenSSL createSSL");
103
+ SSL.createSSL(runtime, _OpenSSL);
104
+ } catch (Throwable e) {
105
+ System.out.println("Got exception creating SSL:");
106
+ e.printStackTrace();
107
+ }
108
+ System.out.println("OpenSSL createOpenSSL createPKCS7");
109
+ PKCS7.createPKCS7(runtime, _OpenSSL);
110
+ System.out.println("OpenSSL createOpenSSL createPKCS5");
111
+ PKCS5.createPKCS5(runtime, _OpenSSL);
112
+
113
+ System.out.println("OpenSSL createOpenSSL require version");
114
+ runtime.getLoadService().require("jopenssl/version");
115
+
116
+ // MRI 1.8.7 :
117
+ // OpenSSL::VERSION: "1.0.0"
118
+ // OpenSSL::OPENSSL_VERSION: "OpenSSL 1.0.1c 10 May 2012"
119
+ // OpenSSL::OPENSSL_VERSION_NUMBER: 268439615
120
+ // MRI 1.9.3 / 2.2.3 :
121
+ // OpenSSL::VERSION: "1.1.0"
122
+ // OpenSSL::OPENSSL_VERSION: "OpenSSL 1.0.1f 6 Jan 2014"
123
+ // OpenSSL::OPENSSL_VERSION_NUMBER: 268439663
124
+ // OpenSSL::OPENSSL_LIBRARY_VERSION: ""OpenSSL 1.0.2d 9 Jul 2015"
125
+ // OpenSSL::FIPS: false
126
+
127
+ System.out.println("OpenSSL createOpenSSL check version");
128
+ final byte[] version = { '1','.','1','.','0' };
129
+ final boolean ruby18 = runtime.getInstanceConfig().getCompatVersion() == CompatVersion.RUBY1_8;
130
+ if ( ruby18 ) version[2] = '0'; // 1.0.0 compatible on 1.8
131
+
132
+ System.out.println("OpenSSL createOpenSSL set version");
133
+ _OpenSSL.setConstant("VERSION", StringHelper.newString(runtime, version));
134
+
135
+ System.out.println("OpenSSL createOpenSSL get Jopenssl version");
136
+ final RubyModule _Jopenssl = runtime.getModule("Jopenssl");
137
+ final RubyModule _Version = (RubyModule) _Jopenssl.getConstantAt("Version");
138
+ final RubyString jVERSION = _Version.getConstantAt("VERSION").asString();
139
+
140
+ final byte[] JRuby_OpenSSL_ = { 'J','R','u','b','y','-','O','p','e','n','S','S','L',' ' };
141
+ final int OPENSSL_VERSION_NUMBER = 999999999; // NOTE: smt more useful?
142
+
143
+ ByteList OPENSSL_VERSION = new ByteList( jVERSION.getByteList().length() + JRuby_OpenSSL_.length );
144
+ OPENSSL_VERSION.setEncoding( jVERSION.getEncoding() );
145
+ OPENSSL_VERSION.append( JRuby_OpenSSL_ );
146
+ OPENSSL_VERSION.append( jVERSION.getByteList() );
147
+
148
+ final RubyString VERSION;
149
+ _OpenSSL.setConstant("OPENSSL_VERSION", VERSION = runtime.newString(OPENSSL_VERSION));
150
+ _OpenSSL.setConstant("OPENSSL_VERSION_NUMBER", runtime.newFixnum(OPENSSL_VERSION_NUMBER));
151
+ if ( ! ruby18 ) {
152
+ // MRI 2.3 tests do: /\AOpenSSL +0\./ !~ OpenSSL::OPENSSL_LIBRARY_VERSION
153
+ _OpenSSL.setConstant("OPENSSL_LIBRARY_VERSION", VERSION);
154
+ _OpenSSL.setConstant("OPENSSL_FIPS", runtime.getFalse());
155
+ }
156
+ System.out.println("OpenSSL createOpenSSL...OK");
157
+ }
158
+
159
+ static RubyClass _OpenSSLError(final Ruby runtime) {
160
+ return runtime.getModule("OpenSSL").getClass("OpenSSLError");
161
+ }
162
+
163
+ // OpenSSL module methods :
164
+
165
+ @JRubyMethod(name = "errors", meta = true)
166
+ public static IRubyObject errors(IRubyObject self) {
167
+ final Ruby runtime = self.getRuntime();
168
+ RubyArray result = runtime.newArray();
169
+ for (Map.Entry<Integer, String> e : X509.getErrors().entrySet()) {
170
+ result.add( runtime.newString( e.getValue() ) );
171
+ }
172
+ return result;
173
+ }
174
+
175
+ @JRubyMethod(name = "debug", meta = true)
176
+ public static IRubyObject getDebug(IRubyObject self) {
177
+ return (IRubyObject) getDebug((RubyModule) self);
178
+ }
179
+
180
+ private static Object getDebug(RubyModule self) {
181
+ return self.getInternalVariable("debug");
182
+ }
183
+
184
+ @JRubyMethod(name = "debug=", meta = true)
185
+ public static IRubyObject setDebug(IRubyObject self, IRubyObject debug) {
186
+ ((RubyModule) self).setInternalVariable("debug", debug);
187
+ OpenSSL.debug = debug.isTrue();
188
+ return debug;
189
+ }
190
+
191
+ @JRubyMethod(name = "Digest", meta = true)
192
+ public static IRubyObject Digest(final IRubyObject self, final IRubyObject name) {
193
+ // OpenSSL::Digest("MD5") -> OpenSSL::Digest::MD5
194
+ final Ruby runtime = self.getRuntime();
195
+ final RubyClass Digest = runtime.getModule("OpenSSL").getClass("Digest");
196
+ return Digest.getConstantAt( name.asString().toString() );
197
+ }
198
+
199
+ // API "stubs" in JRuby-OpenSSL :
200
+
201
+ @JRubyMethod(meta = true)
202
+ public static IRubyObject deprecated_warning_flag(final IRubyObject self) {
203
+ return self.getRuntime().getNil(); // no-op in JRuby-OpenSSL
204
+ }
205
+
206
+ @JRubyMethod(meta = true, rest = true) // check_func(func, header)
207
+ public static IRubyObject check_func(final IRubyObject self, final IRubyObject[] args) {
208
+ return self.getRuntime().getNil(); // no-op in JRuby-OpenSSL
209
+ }
210
+
211
+ // Added in 2.0; not masked because it does nothing anyway (there's no reader in MRI)
212
+ @JRubyMethod(name = "fips_mode=", meta = true)
213
+ public static IRubyObject set_fips_mode(ThreadContext context, IRubyObject self, IRubyObject value) {
214
+ if ( value.isTrue() ) {
215
+ warn(context, "WARNING: FIPS mode not supported on JRuby-OpenSSL");
216
+ }
217
+ return value;
218
+ }
219
+
220
+ // internal (package-level) helpers :
221
+
222
+ private static boolean debug;
223
+
224
+ // on by default, warnings can be disabled using -Djruby.openssl.warn=false
225
+ private static boolean warn = true;
226
+
227
+ static boolean isDebug() { return debug; }
228
+
229
+ static void debugStackTrace(final Throwable e) {
230
+ if ( isDebug() ) e.printStackTrace(System.out);
231
+ }
232
+
233
+ static void debug(final String msg) {
234
+ if ( isDebug() ) System.out.println(msg);
235
+ }
236
+
237
+ static void debug(final String msg, final Throwable e) {
238
+ if ( isDebug() ) System.out.println(msg + ' ' + e);
239
+ }
240
+
241
+ static boolean isDebug(final Ruby runtime) {
242
+ final RubyModule OpenSSL = runtime.getModule("OpenSSL");
243
+ if ( OpenSSL == null ) return debug; // debug early on
244
+ return getDebug( OpenSSL ) == runtime.getTrue();
245
+ }
246
+
247
+ static void debugStackTrace(final Ruby runtime, final Throwable e) {
248
+ if ( isDebug(runtime) ) e.printStackTrace(runtime.getOut());
249
+ }
250
+
251
+ static void debug(final Ruby runtime, final String msg) {
252
+ if ( isDebug(runtime) ) runtime.getOut().println(msg);
253
+ }
254
+
255
+ static void debug(final Ruby runtime, final String msg, final Throwable e) {
256
+ if ( isDebug(runtime) ) runtime.getOut().println(msg + ' ' + e);
257
+ }
258
+
259
+ static void warn(final ThreadContext context, final String msg) {
260
+ warn(context, RubyString.newString(context.runtime, msg));
261
+ }
262
+
263
+ static void warn(final ThreadContext context, final IRubyObject msg) {
264
+ if ( warn ) context.runtime.getModule("OpenSSL").callMethod(context, "warn", msg);
265
+ }
266
+
267
+ private static String javaVersion(final String def) {
268
+ final String javaVersionProperty =
269
+ SafePropertyAccessor.getProperty("java.version", def);
270
+ if (javaVersionProperty == "0") { // Android
271
+ return "1.7.0";
272
+ } else {
273
+ return javaVersionProperty;
274
+ }
275
+ }
276
+
277
+ static boolean javaVersion7(final boolean atLeast) {
278
+ final int gt = "1.7".compareTo( javaVersion("0.0").substring(0, 3) );
279
+ return atLeast ? gt <= 0 : gt == 0;
280
+ }
281
+
282
+ static boolean javaVersion8(final boolean atLeast) {
283
+ final int gt = "1.8".compareTo( javaVersion("0.0").substring(0, 3) );
284
+ return atLeast ? gt <= 0 : gt == 0;
285
+ }
286
+
287
+ private static String javaName(final String def) {
288
+ // Sun Java 6 or Oracle Java 7/8
289
+ // "Java HotSpot(TM) Server VM" or "Java HotSpot(TM) 64-Bit Server VM"
290
+ // OpenJDK :
291
+ // "OpenJDK 64-Bit Server VM"
292
+ return SafePropertyAccessor.getProperty("java.vm.name", def);
293
+ }
294
+
295
+ static boolean javaHotSpot() {
296
+ return javaName("").contains("HotSpot(TM)");
297
+ }
298
+
299
+ static boolean javaOpenJDK() {
300
+ return javaName("").contains("OpenJDK");
301
+ }
302
+
303
+ //
304
+
305
+ static IRubyObject to_der_if_possible(final ThreadContext context, IRubyObject obj) {
306
+ if ( ! obj.respondsTo("to_der")) return obj;
307
+ return obj.callMethod(context, "to_der");
308
+ }
309
+
310
+ //
311
+
312
+ static String bcExceptionMessage(NoSuchProviderException ex) {
313
+ return "You need to configure JVM/classpath to enable BouncyCastle Security Provider: " + ex;
314
+ }
315
+
316
+ static String bcExceptionMessage(NoClassDefFoundError ex) {
317
+ return "You need to configure JVM/classpath to enable BouncyCastle Security Provider: " + ex;
318
+ }
319
+
320
+ }
@@ -10,6 +10,7 @@
10
10
  class Object
11
11
  def with_large_stack(opts = {}, &block)
12
12
  opts = {:size => opts} if opts.is_a? Integer
13
+ opts = {:name => opts} if opts.is_a? String
13
14
  opts = {:name => 'Block with large stack'}.update(opts)
14
15
  exception = nil
15
16
  result = nil
@@ -23,6 +24,7 @@ end
23
24
  class Thread
24
25
  def self.with_large_stack(opts = {}, &block)
25
26
  opts = {:size => opts} if opts.is_a? Integer
27
+ opts = {:name => opts} if opts.is_a? String
26
28
  stack_size_kb = opts.delete(:size) || 64
27
29
  name = opts.delete(:name) || 'Thread with large stack'
28
30
  raise "Unknown option(s): #{opts.inspect}" unless opts.empty?
@@ -5,6 +5,8 @@ require 'ruboto/sdk_locations'
5
5
  module Ruboto
6
6
  module Util
7
7
  module Emulator
8
+ include Ruboto::Util::Verify
9
+
8
10
  ON_WINDOWS = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw/i)
9
11
  ON_MAC_OS_X = RbConfig::CONFIG['host_os'] =~ /^darwin/
10
12
  ON_LINUX = RbConfig::CONFIG['host_os'] =~ /linux/
@@ -19,7 +21,7 @@ module Ruboto
19
21
  STDOUT.sync = true
20
22
  if RbConfig::CONFIG['host_cpu'] == 'x86_64'
21
23
  if ON_MAC_OS_X
22
- emulator_cmd = '-m "emulator64-(arm|x86)"'
24
+ emulator_cmd = '-m "emulator64-(crash-service|arm|x86)"'
23
25
  elsif ON_LINUX
24
26
  emulator_cmd = '-r "emulator64-(arm|x86)"'
25
27
  else
@@ -29,7 +31,9 @@ module Ruboto
29
31
  emulator_cmd = 'emulator-arm'
30
32
  end
31
33
 
32
- avd_name = "Android_#{sdk_level_name(sdk_level)}"
34
+ emulator_config = verify_ruboto_config['emulator']
35
+ avd_name = (emulator_config && emulator_config['name']) || "Android_#{sdk_level_name(sdk_level)}"
36
+ android_device = (emulator_config && emulator_config['device']) || "Nexus One"
33
37
  new_snapshot = false
34
38
 
35
39
  if `adb devices` =~ /emulator-5554/
@@ -57,8 +61,8 @@ module Ruboto
57
61
  # FIXME(uwe): Change use of "killall" to use the Ruby Process API
58
62
  loop do
59
63
  emulator_opts = '-partition-size 256'
60
- emulator_opts << ' -noskin'
61
- emulator_opts << ' -no-snapshot-load' if no_snapshot
64
+ emulator_opts << ' -noskin' unless android_device
65
+ emulator_opts << ' -no-snapshot' if no_snapshot
62
66
  if !ON_MAC_OS_X && !ON_WINDOWS && ENV['DISPLAY'].nil?
63
67
  emulator_opts << ' -no-window -no-audio'
64
68
  end
@@ -90,15 +94,13 @@ module Ruboto
90
94
  avd_home = "#{ENV['HOME'].gsub('\\', '/')}/.android/avd/#{avd_name}.avd"
91
95
  manifest_file = 'AndroidManifest.xml'
92
96
  large_heap = (!File.exists?(manifest_file)) || (File.read(manifest_file) =~ /largeHeap/)
93
- heap_size = large_heap ? 256 : 48
97
+ heap_size = large_heap ? 256 : 64
94
98
 
95
- unless File.exists? avd_home
96
- create_avd(avd_home, avd_name, heap_size, sdk_level)
97
- new_snapshot = true
99
+ if File.exists? avd_home
100
+ patch_config_ini(avd_home, heap_size, no_snapshot)
98
101
  else
99
- # FIXME(uwe): Patch old emulator AVDs. Remove December 2016.
100
- patch_config_ini(avd_home, heap_size)
101
- # EMXIF
102
+ create_avd(avd_home, avd_name, android_device, heap_size, sdk_level)
103
+ new_snapshot = true
102
104
  end
103
105
 
104
106
  puts "Start emulator #{avd_name}#{' without snapshot' if no_snapshot}"
@@ -121,7 +123,7 @@ module Ruboto
121
123
  `killall -0 #{emulator_cmd} 2> /dev/null`
122
124
  if $? != 0
123
125
  puts 'Unable to start the emulator. Retrying without loading snapshot.'
124
- system "emulator -no-snapshot-load -avd #{avd_name} #{emulator_opts} #{'&' unless ON_WINDOWS}"
126
+ system "emulator -no-snapshot -avd #{avd_name} #{emulator_opts} #{'&' unless ON_WINDOWS}"
125
127
  10.times do |i|
126
128
  `killall -0 #{emulator_cmd} 2> /dev/null`
127
129
  if $? == 0
@@ -191,7 +193,7 @@ EOF
191
193
  puts "Emulator #{avd_name} started OK."
192
194
  end
193
195
 
194
- def create_avd(avd_home, avd_name, heap_size, sdk_level)
196
+ def create_avd(avd_home, avd_name, android_device, heap_size, sdk_level)
195
197
  puts "Creating AVD #{avd_name}"
196
198
 
197
199
  target = `android list target`.split(/----------\n/).
@@ -224,7 +226,12 @@ EOF
224
226
  abi_opt = '--abi armeabi-v7a'
225
227
  end
226
228
 
227
- skin = 'HVGA'
229
+ ruboto_config_filename = 'ruboto.yml'
230
+ if File.exists?(ruboto_config_filename)
231
+ ruboto_config = YAML.load_file(ruboto_config_filename)
232
+ skin = ruboto_config['emulator'] && ruboto_config['emulator']['skin']
233
+ end
234
+ skin ||= '768x1280'
228
235
  # skin_filename = "#{Ruboto::SdkLocations::ANDROID_HOME}/platforms/android-#{sdk_level}/skins/#{skin}/hardware.ini"
229
236
  # if File.exists?(skin_filename)
230
237
  # old_skin_config = File.read(skin_filename)
@@ -234,7 +241,7 @@ EOF
234
241
  # File.write(skin_filename, new_skin_config) if new_skin_config != old_skin_config
235
242
  # end
236
243
 
237
- puts `echo no | android create avd -a -n #{avd_name} -t android-#{sdk_level} #{abi_opt} -c 64M -s #{skin} -d "Nexus One"`
244
+ puts `echo no | android create avd -a -n #{avd_name} -t android-#{sdk_level} #{abi_opt} -c 64M #{"-s #{skin}" if skin} -d "#{android_device}"`
238
245
 
239
246
  if $? != 0
240
247
  puts 'Failed to create AVD.'
@@ -242,25 +249,34 @@ EOF
242
249
  end
243
250
  patch_config_ini(avd_home, heap_size)
244
251
 
245
- # hw_config_file_name = "#{avd_home}/hardware-qemu.ini"
246
- # if File.exists?(hw_config_file_name)
247
- # old_hw_config = File.read(hw_config_file_name)
248
- # new_hw_config = old_hw_config.gsub(/vm.heapSize=([0-9]*)/) { |m| $1.to_i < heap_size ? "vm.heapSize=#{heap_size}" : m }
249
- # File.write(hw_config_file_name, new_hw_config) if new_hw_config != old_hw_config
250
- # end
252
+ hw_config_file_name = "#{avd_home}/hardware-qemu.ini"
253
+ if File.exists?(hw_config_file_name)
254
+ old_hw_config = File.read(hw_config_file_name)
255
+ new_hw_config = old_hw_config.dup
256
+ update_heap_size(new_hw_config, heap_size)
257
+ File.write(hw_config_file_name, new_hw_config) if new_hw_config != old_hw_config
258
+ end
251
259
  end
252
260
 
253
- def patch_config_ini(avd_home, heap_size)
261
+ def update_heap_size(new_hw_config, heap_size)
262
+ old_heap = read_property(new_hw_config, 'vm.heapSize')
263
+ if old_heap.nil? || old_heap.to_i < heap_size
264
+ add_property(new_hw_config, 'vm.heapSize', heap_size)
265
+ end
266
+ end
267
+
268
+ def patch_config_ini(avd_home, heap_size, no_snapshot)
254
269
  avd_config_file_name = "#{avd_home}/config.ini"
255
270
  old_avd_config = File.read(avd_config_file_name)
256
271
  new_avd_config = old_avd_config.dup
257
- new_avd_config.gsub!(/vm.heapSize=([0-9]*)/) { |m| $1.to_i < heap_size ? "vm.heapSize=#{heap_size}" : m }
272
+ update_heap_size(new_avd_config, heap_size)
258
273
  # add_property(new_avd_config, 'hw.device.manufacturer', 'Generic')
259
274
  # add_property(new_avd_config, 'hw.device.name', '3.2" HVGA slider (ADP1)')
260
275
  # add_property(new_avd_config, 'hw.keyboard.lid', 'no')
261
- add_property(new_avd_config, 'hw.lcd.density', '160')
276
+ # add_property(new_avd_config, 'hw.lcd.density', '160')
262
277
  add_property(new_avd_config, 'hw.mainKeys', 'no')
263
278
  # add_property(new_avd_config, 'hw.sdCard', 'yes')
279
+ add_property(new_avd_config, 'snapshot.present', (!no_snapshot).to_s)
264
280
  File.write(avd_config_file_name, new_avd_config) if new_avd_config != old_avd_config
265
281
  end
266
282
 
@@ -268,17 +284,23 @@ EOF
268
284
  `adb get-state`.gsub(/^WARNING:.*$/, '').chomp == 'device'
269
285
  end
270
286
 
271
- def add_property(new_avd_config, property_name, value)
287
+ def read_property(config, property_name)
288
+ pattern = /^#{property_name}=(.*)$/
289
+ config =~ pattern
290
+ $1
291
+ end
292
+
293
+ def add_property(config, property_name, value)
272
294
  pattern = /^#{property_name}=(.*)$/
273
- property = "#{property_name}=#{value}"
274
- if new_avd_config =~ pattern
275
- if $1 != value
276
- new_avd_config.gsub! pattern, property
277
- puts "Changed property: #{property}"
295
+ new_property = "#{property_name}=#{value}"
296
+ if (old_property = read_property(config, property_name))
297
+ if old_property != value
298
+ config.gsub! pattern, new_property
299
+ puts "Changed property: #{new_property} (was #{old_property.inspect})"
278
300
  end
279
301
  else
280
- new_avd_config << "#{property}\n"
281
- puts "Added property: #{property}"
302
+ config << "#{new_property}\n"
303
+ puts "Added property: #{new_property}"
282
304
  end
283
305
  end
284
306
  end