Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
b460d0ee
Unverified
Commit
b460d0ee
authored
Nov 19, 2021
by
Jenn Magder
Committed by
GitHub
Nov 19, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Migrate emulators to null safety (#92738)
parent
9bff08b7
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
112 additions
and
80 deletions
+112
-80
android_emulator.dart
packages/flutter_tools/lib/src/android/android_emulator.dart
+26
-23
emulator.dart
packages/flutter_tools/lib/src/emulator.dart
+56
-47
ios_emulators.dart
packages/flutter_tools/lib/src/ios/ios_emulators.dart
+8
-5
android_emulator_test.dart
...ols/test/general.shard/android/android_emulator_test.dart
+22
-4
emulator_test.dart
packages/flutter_tools/test/general.shard/emulator_test.dart
+0
-1
No files found.
packages/flutter_tools/lib/src/android/android_emulator.dart
View file @
b460d0ee
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'package:meta/meta.dart'
;
...
...
@@ -23,11 +21,11 @@ import 'android_sdk.dart';
class
AndroidEmulators
extends
EmulatorDiscovery
{
AndroidEmulators
({
@required
AndroidSdk
androidSdk
,
@
required
AndroidWorkflow
androidWorkflow
,
@
required
FileSystem
fileSystem
,
@
required
Logger
logger
,
@
required
ProcessManager
processManager
,
AndroidSdk
?
androidSdk
,
required
AndroidWorkflow
androidWorkflow
,
required
FileSystem
fileSystem
,
required
Logger
logger
,
required
ProcessManager
processManager
,
})
:
_androidSdk
=
androidSdk
,
_androidWorkflow
=
androidWorkflow
,
_fileSystem
=
fileSystem
,
...
...
@@ -36,7 +34,7 @@ class AndroidEmulators extends EmulatorDiscovery {
_processUtils
=
ProcessUtils
(
logger:
logger
,
processManager:
processManager
);
final
AndroidWorkflow
_androidWorkflow
;
final
AndroidSdk
_androidSdk
;
final
AndroidSdk
?
_androidSdk
;
final
FileSystem
_fileSystem
;
final
Logger
_logger
;
final
ProcessManager
_processManager
;
...
...
@@ -50,14 +48,14 @@ class AndroidEmulators extends EmulatorDiscovery {
@override
bool
get
canLaunchAnything
=>
_androidWorkflow
.
canListEmulators
&&
_androidSdk
.
getAvdManagerPath
()
!=
null
;
&&
_androidSdk
?
.
getAvdManagerPath
()
!=
null
;
@override
Future
<
List
<
Emulator
>>
get
emulators
=>
_getEmulatorAvds
();
/// Return the list of available emulator AVDs.
Future
<
List
<
AndroidEmulator
>>
_getEmulatorAvds
()
async
{
final
String
emulatorPath
=
_androidSdk
?.
emulatorPath
;
final
String
?
emulatorPath
=
_androidSdk
?.
emulatorPath
;
if
(
emulatorPath
==
null
)
{
return
<
AndroidEmulator
>[];
}
...
...
@@ -82,7 +80,7 @@ class AndroidEmulators extends EmulatorDiscovery {
AndroidEmulator
_loadEmulatorInfo
(
String
id
)
{
id
=
id
.
trim
();
final
String
avdPath
=
_androidSdk
.
getAvdPath
();
final
String
?
avdPath
=
_androidSdk
?
.
getAvdPath
();
final
AndroidEmulator
androidEmulatorWithoutProperties
=
AndroidEmulator
(
id
,
processManager:
_processManager
,
...
...
@@ -97,10 +95,11 @@ class AndroidEmulators extends EmulatorDiscovery {
return
androidEmulatorWithoutProperties
;
}
final
Map
<
String
,
String
>
ini
=
parseIniLines
(
iniFile
.
readAsLinesSync
());
if
(
ini
[
'path'
]
==
null
)
{
final
String
?
path
=
ini
[
'path'
];
if
(
path
==
null
)
{
return
androidEmulatorWithoutProperties
;
}
final
File
configFile
=
_fileSystem
.
file
(
_fileSystem
.
path
.
join
(
ini
[
'path'
]
,
'config.ini'
));
final
File
configFile
=
_fileSystem
.
file
(
_fileSystem
.
path
.
join
(
path
,
'config.ini'
));
if
(!
configFile
.
existsSync
())
{
return
androidEmulatorWithoutProperties
;
}
...
...
@@ -117,20 +116,20 @@ class AndroidEmulators extends EmulatorDiscovery {
class
AndroidEmulator
extends
Emulator
{
AndroidEmulator
(
String
id
,
{
Map
<
String
,
String
>
properties
,
@
required
Logger
logger
,
@required
AndroidSdk
androidSdk
,
@
required
ProcessManager
processManager
,
Map
<
String
,
String
>
?
properties
,
required
Logger
logger
,
AndroidSdk
?
androidSdk
,
required
ProcessManager
processManager
,
})
:
_properties
=
properties
,
_logger
=
logger
,
_androidSdk
=
androidSdk
,
_processUtils
=
ProcessUtils
(
logger:
logger
,
processManager:
processManager
),
super
(
id
,
properties
!=
null
&&
properties
.
isNotEmpty
);
final
Map
<
String
,
String
>
_properties
;
final
Map
<
String
,
String
>
?
_properties
;
final
Logger
_logger
;
final
ProcessUtils
_processUtils
;
final
AndroidSdk
_androidSdk
;
final
AndroidSdk
?
_androidSdk
;
// Android Studio uses the ID with underscores replaced with spaces
// for the name if displayname is not set so we do the same.
...
...
@@ -138,7 +137,7 @@ class AndroidEmulator extends Emulator {
String
get
name
=>
_prop
(
'avd.ini.displayname'
)
??
id
.
replaceAll
(
'_'
,
' '
).
trim
();
@override
String
get
manufacturer
=>
_prop
(
'hw.device.manufacturer'
);
String
?
get
manufacturer
=>
_prop
(
'hw.device.manufacturer'
);
@override
Category
get
category
=>
Category
.
mobile
;
...
...
@@ -146,12 +145,16 @@ class AndroidEmulator extends Emulator {
@override
PlatformType
get
platformType
=>
PlatformType
.
android
;
String
_prop
(
String
name
)
=>
_properties
!=
null
?
_properties
[
name
]
:
null
;
String
?
_prop
(
String
name
)
=>
_properties
!=
null
?
_properties
!
[
name
]
:
null
;
@override
Future
<
void
>
launch
({
@visibleForTesting
Duration
startupDuration
,
bool
coldBoot
=
false
})
async
{
Future
<
void
>
launch
({
@visibleForTesting
Duration
?
startupDuration
,
bool
coldBoot
=
false
})
async
{
final
String
?
emulatorPath
=
_androidSdk
?.
emulatorPath
;
if
(
emulatorPath
==
null
)
{
throw
Exception
(
'Emulator is missing from the Android SDK'
);
}
final
List
<
String
>
command
=
<
String
>[
_androidSdk
.
emulatorPath
,
emulatorPath
,
'-avd'
,
id
,
if
(
coldBoot
)
...
...
packages/flutter_tools/lib/src/emulator.dart
View file @
b460d0ee
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'dart:math'
as
math
;
import
'package:meta/meta.dart'
;
...
...
@@ -19,16 +17,16 @@ import 'base/process.dart';
import
'device.dart'
;
import
'ios/ios_emulators.dart'
;
EmulatorManager
get
emulatorManager
=>
context
.
get
<
EmulatorManager
>();
EmulatorManager
?
get
emulatorManager
=>
context
.
get
<
EmulatorManager
>();
/// A class to get all available emulators.
class
EmulatorManager
{
EmulatorManager
({
@required
AndroidSdk
androidSdk
,
@
required
Logger
logger
,
@
required
ProcessManager
processManager
,
@
required
AndroidWorkflow
androidWorkflow
,
@
required
FileSystem
fileSystem
,
AndroidSdk
?
androidSdk
,
required
Logger
logger
,
required
ProcessManager
processManager
,
required
AndroidWorkflow
androidWorkflow
,
required
FileSystem
fileSystem
,
})
:
_androidSdk
=
androidSdk
,
_processUtils
=
ProcessUtils
(
logger:
logger
,
processManager:
processManager
),
_androidEmulators
=
AndroidEmulators
(
...
...
@@ -41,7 +39,7 @@ class EmulatorManager {
_emulatorDiscoverers
.
add
(
_androidEmulators
);
}
final
AndroidSdk
_androidSdk
;
final
AndroidSdk
?
_androidSdk
;
final
AndroidEmulators
_androidEmulators
;
final
ProcessUtils
_processUtils
;
...
...
@@ -55,14 +53,19 @@ class EmulatorManager {
final
List
<
Emulator
>
emulators
=
await
getAllAvailableEmulators
();
searchText
=
searchText
.
toLowerCase
();
bool
exactlyMatchesEmulatorId
(
Emulator
emulator
)
=>
emulator
.
id
?
.
toLowerCase
()
==
searchText
||
emulator
.
name
?
.
toLowerCase
()
==
searchText
;
emulator
.
id
.
toLowerCase
()
==
searchText
||
emulator
.
name
.
toLowerCase
()
==
searchText
;
bool
startsWithEmulatorId
(
Emulator
emulator
)
=>
emulator
.
id
?.
toLowerCase
()?.
startsWith
(
searchText
)
==
true
||
emulator
.
name
?.
toLowerCase
()?.
startsWith
(
searchText
)
==
true
;
final
Emulator
exactMatch
=
emulators
.
firstWhere
(
exactlyMatchesEmulatorId
,
orElse:
()
=>
null
);
emulator
.
id
.
toLowerCase
().
startsWith
(
searchText
)
==
true
||
emulator
.
name
.
toLowerCase
().
startsWith
(
searchText
)
==
true
;
Emulator
?
exactMatch
;
for
(
final
Emulator
emulator
in
emulators
)
{
if
(
exactlyMatchesEmulatorId
(
emulator
))
{
exactMatch
=
emulator
;
break
;
}
}
if
(
exactMatch
!=
null
)
{
return
<
Emulator
>[
exactMatch
];
}
...
...
@@ -85,7 +88,7 @@ class EmulatorManager {
}
/// Return the list of all available emulators.
Future
<
CreateEmulatorResult
>
createEmulator
({
String
name
})
async
{
Future
<
CreateEmulatorResult
>
createEmulator
({
String
?
name
})
async
{
if
(
name
==
null
||
name
.
isEmpty
)
{
const
String
autoName
=
'flutter_emulator'
;
// Don't use getEmulatorsMatching here, as it will only return one
...
...
@@ -102,21 +105,23 @@ class EmulatorManager {
name
=
'
${autoName}
_
${++suffix}
'
;
}
}
if
(!
_androidEmulators
.
canLaunchAnything
)
{
return
CreateEmulatorResult
(
name
,
final
String
emulatorName
=
name
!;
final
String
?
avdManagerPath
=
_androidSdk
?.
avdManagerPath
;
if
(
avdManagerPath
==
null
||
!
_androidEmulators
.
canLaunchAnything
)
{
return
CreateEmulatorResult
(
emulatorName
,
success:
false
,
error:
'avdmanager is missing from the Android SDK'
);
}
final
String
device
=
await
_getPreferredAvailableDevice
(
);
final
String
?
device
=
await
_getPreferredAvailableDevice
(
avdManagerPath
);
if
(
device
==
null
)
{
return
CreateEmulatorResult
(
n
ame
,
return
CreateEmulatorResult
(
emulatorN
ame
,
success:
false
,
error:
'No device definitions are available'
);
}
final
String
sdkId
=
await
_getPreferredSdkId
(
);
final
String
?
sdkId
=
await
_getPreferredSdkId
(
avdManagerPath
);
if
(
sdkId
==
null
)
{
return
CreateEmulatorResult
(
n
ame
,
return
CreateEmulatorResult
(
emulatorN
ame
,
success:
false
,
error:
'No suitable Android AVD system images are available. You may need to install these'
...
...
@@ -128,7 +133,7 @@ class EmulatorManager {
// to flutter users. Specifically:
// - Removes lines that say "null" (!)
// - Removes lines that tell the user to use '--force' to overwrite emulators
String
cleanError
(
String
error
)
{
String
?
cleanError
(
String
?
error
)
{
if
(
error
==
null
||
error
.
trim
()
==
''
)
{
return
null
;
}
...
...
@@ -141,16 +146,16 @@ class EmulatorManager {
.
trim
();
}
final
RunResult
runResult
=
await
_processUtils
.
run
(<
String
>[
_androidSdk
?.
avdManagerPath
,
avdManagerPath
,
'create'
,
'avd'
,
'-n'
,
n
ame
,
'-n'
,
emulatorN
ame
,
'-k'
,
sdkId
,
'-d'
,
device
,
],
environment:
_androidSdk
?.
sdkManagerEnv
,
);
return
CreateEmulatorResult
(
n
ame
,
emulatorN
ame
,
success:
runResult
.
exitCode
==
0
,
output:
runResult
.
stdout
,
error:
cleanError
(
runResult
.
stderr
),
...
...
@@ -162,9 +167,9 @@ class EmulatorManager {
'pixel_xl'
,
];
Future
<
String
>
_getPreferredAvailableDevice
(
)
async
{
Future
<
String
?>
_getPreferredAvailableDevice
(
String
avdManagerPath
)
async
{
final
List
<
String
>
args
=
<
String
>[
_androidSdk
?.
avdManagerPath
,
avdManagerPath
,
'list'
,
'device'
,
'-c'
,
...
...
@@ -180,19 +185,21 @@ class EmulatorManager {
.
where
((
String
l
)
=>
preferredDevices
.
contains
(
l
.
trim
()))
.
toList
();
return
preferredDevices
.
firstWhere
(
(
String
d
)
=>
availableDevices
.
contains
(
d
),
orElse:
()
=>
null
,
);
for
(
final
String
device
in
preferredDevices
)
{
if
(
availableDevices
.
contains
(
device
))
{
return
device
;
}
}
return
null
;
}
static
final
RegExp
_androidApiVersion
=
RegExp
(
r';android-(\d+);'
);
Future
<
String
>
_getPreferredSdkId
(
)
async
{
Future
<
String
?>
_getPreferredSdkId
(
String
avdManagerPath
)
async
{
// It seems that to get the available list of images, we need to send a
// request to create without the image and it'll provide us a list :-(
final
List
<
String
>
args
=
<
String
>[
_androidSdk
?.
avdManagerPath
,
avdManagerPath
,
'create'
,
'avd'
,
'-n'
,
'temp'
,
...
...
@@ -209,7 +216,7 @@ class EmulatorManager {
.
toList
();
final
List
<
int
>
availableApiVersions
=
availableIDs
.
map
<
String
>((
String
id
)
=>
_androidApiVersion
.
firstMatch
(
id
)
.
group
(
1
)
)
.
map
<
String
>((
String
id
)
=>
_androidApiVersion
.
firstMatch
(
id
)
!.
group
(
1
)!
)
.
map
<
int
>((
String
apiVersion
)
=>
int
.
parse
(
apiVersion
))
.
toList
();
...
...
@@ -220,10 +227,12 @@ class EmulatorManager {
// We're out of preferences, we just have to return the first one with the high
// API version.
return
availableIDs
.
firstWhere
(
(
String
id
)
=>
id
.
contains
(
';android-
$apiVersion
;'
),
orElse:
()
=>
null
,
);
for
(
final
String
id
in
availableIDs
)
{
if
(
id
.
contains
(
';android-
$apiVersion
;'
))
{
return
id
;
}
}
return
null
;
}
/// Whether we're capable of listing any emulators given the current environment configuration.
...
...
@@ -252,7 +261,7 @@ abstract class Emulator {
final
String
id
;
final
bool
hasConfig
;
String
get
name
;
String
get
manufacturer
;
String
?
get
manufacturer
;
Category
get
category
;
PlatformType
get
platformType
;
...
...
@@ -282,10 +291,10 @@ abstract class Emulator {
final
List
<
List
<
String
>>
table
=
<
List
<
String
>>[
for
(
final
Emulator
emulator
in
emulators
)
<
String
>[
emulator
.
id
??
''
,
emulator
.
name
??
''
,
emulator
.
id
,
emulator
.
name
,
emulator
.
manufacturer
??
''
,
emulator
.
platformType
?.
toString
()
??
''
,
emulator
.
platformType
.
toString
()
,
],
];
...
...
@@ -315,10 +324,10 @@ abstract class Emulator {
}
class
CreateEmulatorResult
{
CreateEmulatorResult
(
this
.
emulatorName
,
{
this
.
success
,
this
.
output
,
this
.
error
});
CreateEmulatorResult
(
this
.
emulatorName
,
{
required
this
.
success
,
this
.
output
,
this
.
error
});
final
bool
success
;
final
String
emulatorName
;
final
String
output
;
final
String
error
;
final
String
?
output
;
final
String
?
error
;
}
packages/flutter_tools/lib/src/ios/ios_emulators.dart
View file @
b460d0ee
...
...
@@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'../base/common.dart'
;
import
'../base/process.dart'
;
import
'../device.dart'
;
import
'../emulator.dart'
;
...
...
@@ -15,7 +14,7 @@ class IOSEmulators extends EmulatorDiscovery {
bool
get
supportsPlatform
=>
globals
.
platform
.
isMacOS
;
@override
bool
get
canListAnything
=>
globals
.
iosWorkflow
.
canListEmulators
;
bool
get
canListAnything
=>
globals
.
iosWorkflow
?.
canListEmulators
==
true
;
@override
Future
<
List
<
Emulator
>>
get
emulators
async
=>
getEmulators
();
...
...
@@ -41,12 +40,16 @@ class IOSEmulator extends Emulator {
@override
Future
<
void
>
launch
({
bool
coldBoot
=
false
})
async
{
final
String
?
simulatorPath
=
globals
.
xcode
?.
getSimulatorPath
();
if
(
simulatorPath
==
null
)
{
throwToolExit
(
'Could not find Simulator app'
);
}
Future
<
bool
>
launchSimulator
(
List
<
String
>
additionalArgs
)
async
{
final
List
<
String
>
args
=
<
String
>[
'open'
,
...
additionalArgs
,
'-a'
,
globals
.
xcode
.
getSimulatorPath
()
,
simulatorPath
,
];
final
RunResult
launchResult
=
await
globals
.
processUtils
.
run
(
args
);
...
...
@@ -70,7 +73,7 @@ class IOSEmulator extends Emulator {
/// Return the list of iOS Simulators (there can only be zero or one).
List
<
IOSEmulator
>
getEmulators
()
{
final
String
simulatorPath
=
globals
.
xcode
.
getSimulatorPath
();
final
String
?
simulatorPath
=
globals
.
xcode
?
.
getSimulatorPath
();
if
(
simulatorPath
==
null
)
{
return
<
IOSEmulator
>[];
}
...
...
packages/flutter_tools/test/general.shard/android/android_emulator_test.dart
View file @
b460d0ee
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'package:flutter_tools/src/android/android_emulator.dart'
;
...
...
@@ -125,7 +123,7 @@ void main() {
});
group
(
'Android emulator launch '
,
()
{
FakeAndroidSdk
mockSdk
;
late
FakeAndroidSdk
mockSdk
;
setUp
(()
{
mockSdk
=
FakeAndroidSdk
();
...
...
@@ -198,10 +196,30 @@ void main() {
expect
(
logger
.
errorText
,
isEmpty
);
});
testWithoutContext
(
'throws if emulator not found'
,
()
async
{
mockSdk
.
emulatorPath
=
null
;
final
AndroidEmulator
emulator
=
AndroidEmulator
(
emulatorID
,
processManager:
FakeProcessManager
.
empty
(),
androidSdk:
mockSdk
,
logger:
BufferLogger
.
test
(),
);
await
expectLater
(
()
=>
emulator
.
launch
(
startupDuration:
Duration
.
zero
),
throwsA
(
isException
.
having
(
(
Exception
exception
)
=>
exception
.
toString
(),
'description'
,
contains
(
'Emulator is missing from the Android SDK'
),
)),
);
});
});
}
class
FakeAndroidSdk
extends
Fake
implements
AndroidSdk
{
@override
String
emulatorPath
;
String
?
emulatorPath
;
}
packages/flutter_tools/test/general.shard/emulator_test.dart
View file @
b460d0ee
...
...
@@ -97,7 +97,6 @@ void main() {
stdout:
'existing-avd-1'
,
),
]),
androidSdk:
null
,
androidWorkflow:
AndroidWorkflow
(
androidSdk:
sdk
,
featureFlags:
TestFeatureFlags
(),
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment