ruboto 1.4.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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