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
0c9a4205
Unverified
Commit
0c9a4205
authored
Oct 30, 2021
by
Jenn Magder
Committed by
GitHub
Oct 30, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Migrate android_device to null safety (#92128)
parent
53e04de6
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
205 additions
and
251 deletions
+205
-251
android_device.dart
packages/flutter_tools/lib/src/android/android_device.dart
+166
-170
android_device_discovery.dart
...utter_tools/lib/src/android/android_device_discovery.dart
+23
-25
adb_log_reader_test.dart
...tools/test/general.shard/android/adb_log_reader_test.dart
+1
-3
android_device_discovery_test.dart
.../general.shard/android/android_device_discovery_test.dart
+0
-1
android_device_port_forwarder_test.dart
...ral.shard/android/android_device_port_forwarder_test.dart
+0
-2
android_device_start_test.dart
...test/general.shard/android/android_device_start_test.dart
+3
-5
android_device_stop_test.dart
.../test/general.shard/android/android_device_stop_test.dart
+0
-31
android_device_test.dart
...tools/test/general.shard/android/android_device_test.dart
+6
-7
android_install_test.dart
...ools/test/general.shard/android/android_install_test.dart
+6
-7
No files found.
packages/flutter_tools/lib/src/android/android_device.dart
View file @
0c9a4205
...
...
@@ -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'
;
...
...
@@ -60,13 +58,13 @@ class AndroidDevice extends Device {
AndroidDevice
(
String
id
,
{
this
.
productID
,
this
.
modelID
,
required
this
.
modelID
,
this
.
deviceCodeName
,
@
required
Logger
logger
,
@
required
ProcessManager
processManager
,
@
required
Platform
platform
,
@
required
AndroidSdk
androidSdk
,
@
required
FileSystem
fileSystem
,
required
Logger
logger
,
required
ProcessManager
processManager
,
required
Platform
platform
,
required
AndroidSdk
androidSdk
,
required
FileSystem
fileSystem
,
AndroidConsoleSocketFactory
androidConsoleSocketFactory
=
kAndroidConsoleSocketFactory
,
})
:
_logger
=
logger
,
_processManager
=
processManager
,
...
...
@@ -90,60 +88,53 @@ class AndroidDevice extends Device {
final
ProcessUtils
_processUtils
;
final
AndroidConsoleSocketFactory
_androidConsoleSocketFactory
;
final
String
productID
;
final
String
?
productID
;
final
String
modelID
;
final
String
deviceCodeName
;
Map
<
String
,
String
>
_properties
;
bool
_isLocalEmulator
;
TargetPlatform
_applicationPlatform
;
final
String
?
deviceCodeName
;
Future
<
String
>
_getProperty
(
String
name
)
async
{
if
(
_properties
==
null
)
{
_properties
=
<
String
,
String
>{};
late
final
Future
<
Map
<
String
,
String
>>
_properties
=
()
async
{
Map
<
String
,
String
>
properties
=
<
String
,
String
>{};
final
List
<
String
>
propCommand
=
adbCommandForDevice
(<
String
>[
'shell'
,
'getprop'
]);
_logger
.
printTrace
(
propCommand
.
join
(
' '
));
final
List
<
String
>
propCommand
=
adbCommandForDevice
(<
String
>[
'shell'
,
'getprop'
]);
_logger
.
printTrace
(
propCommand
.
join
(
' '
));
try
{
// We pass an encoding of latin1 so that we don't try and interpret the
// `adb shell getprop` result as UTF8.
final
ProcessResult
result
=
await
_processManager
.
run
(
propCommand
,
stdoutEncoding:
latin1
,
stderrEncoding:
latin1
,
);
if
(
result
.
exitCode
==
0
||
_allowHeapCorruptionOnWindows
(
result
.
exitCode
,
_platform
))
{
_properties
=
parseAdbDeviceProperties
(
result
.
stdout
as
String
);
}
else
{
_logger
.
printError
(
'Error
${result.exitCode}
retrieving device properties for
$name
:'
);
_logger
.
printError
(
result
.
stderr
as
String
);
}
}
on
ProcessException
catch
(
error
)
{
_logger
.
printError
(
'Error retrieving device properties for
$name
:
$error
'
);
try
{
// We pass an encoding of latin1 so that we don't try and interpret the
// `adb shell getprop` result as UTF8.
final
ProcessResult
result
=
await
_processManager
.
run
(
propCommand
,
stdoutEncoding:
latin1
,
stderrEncoding:
latin1
,
);
if
(
result
.
exitCode
==
0
||
_allowHeapCorruptionOnWindows
(
result
.
exitCode
,
_platform
))
{
properties
=
parseAdbDeviceProperties
(
result
.
stdout
as
String
);
}
else
{
_logger
.
printError
(
'Error
${result.exitCode}
retrieving device properties for
$name
:'
);
_logger
.
printError
(
result
.
stderr
as
String
);
}
}
on
ProcessException
catch
(
error
)
{
_logger
.
printError
(
'Error retrieving device properties for
$name
:
$error
'
);
}
return
properties
;
}();
return
_properties
[
name
];
Future
<
String
?>
_getProperty
(
String
name
)
async
{
return
(
await
_properties
)[
name
];
}
@override
Future
<
bool
>
get
isLocalEmulator
async
{
if
(
_isLocalEmulator
==
null
)
{
final
String
hardware
=
await
_getProperty
(
'ro.hardware'
);
_logger
.
printTrace
(
'ro.hardware =
$hardware
'
);
if
(
kKnownHardware
.
containsKey
(
hardware
))
{
// Look for known hardware models.
_isLocalEmulator
=
kKnownHardware
[
hardware
]
==
HardwareType
.
emulator
;
}
else
{
// Fall back to a best-effort heuristic-based approach.
final
String
characteristics
=
await
_getProperty
(
'ro.build.characteristics'
);
_logger
.
printTrace
(
'ro.build.characteristics =
$characteristics
'
);
_isLocalEmulator
=
characteristics
!=
null
&&
characteristics
.
contains
(
'emulator'
);
}
late
final
Future
<
bool
>
isLocalEmulator
=
()
async
{
final
String
?
hardware
=
await
_getProperty
(
'ro.hardware'
);
_logger
.
printTrace
(
'ro.hardware =
$hardware
'
);
if
(
kKnownHardware
.
containsKey
(
hardware
))
{
// Look for known hardware models.
return
kKnownHardware
[
hardware
]
==
HardwareType
.
emulator
;
}
return
_isLocalEmulator
;
}
// Fall back to a best-effort heuristic-based approach.
final
String
?
characteristics
=
await
_getProperty
(
'ro.build.characteristics'
);
_logger
.
printTrace
(
'ro.build.characteristics =
$characteristics
'
);
return
characteristics
!=
null
&&
characteristics
.
contains
(
'emulator'
);
}();
/// The unique identifier for the emulator that corresponds to this device, or
/// null if it is not an emulator.
...
...
@@ -152,7 +143,7 @@ class AndroidDevice extends Device {
/// this name may require connecting to the device and if an error occurs null
/// will be returned.
@override
Future
<
String
>
get
emulatorId
async
{
Future
<
String
?
>
get
emulatorId
async
{
if
(!(
await
isLocalEmulator
))
{
return
null
;
}
...
...
@@ -161,13 +152,13 @@ class AndroidDevice extends Device {
// Android Console port number.
final
RegExp
emulatorPortRegex
=
RegExp
(
r'emulator-(\d+)'
);
final
Match
portMatch
=
emulatorPortRegex
.
firstMatch
(
id
);
final
Match
?
portMatch
=
emulatorPortRegex
.
firstMatch
(
id
);
if
(
portMatch
==
null
||
portMatch
.
groupCount
<
1
)
{
return
null
;
}
const
String
host
=
'localhost'
;
final
int
port
=
int
.
parse
(
portMatch
.
group
(
1
));
final
int
port
=
int
.
parse
(
portMatch
.
group
(
1
)
!
);
_logger
.
printTrace
(
'Fetching avd name for
$name
via Android console on
$host
:
$port
'
);
try
{
...
...
@@ -196,36 +187,28 @@ class AndroidDevice extends Device {
}
@override
Future
<
TargetPlatform
>
get
targetPlatform
async
{
if
(
_applicationPlatform
==
null
)
{
// http://developer.android.com/ndk/guides/abis.html (x86, armeabi-v7a, ...)
switch
(
await
_getProperty
(
'ro.product.cpu.abi'
))
{
case
'arm64-v8a'
:
// Perform additional verification for 64 bit ABI. Some devices,
// like the Kindle Fire 8, misreport the abilist. We might not
// be able to retrieve this property, in which case we fall back
// to assuming 64 bit.
final
String
abilist
=
await
_getProperty
(
'ro.product.cpu.abilist'
);
if
(
abilist
==
null
||
abilist
.
contains
(
'arm64-v8a'
))
{
_applicationPlatform
=
TargetPlatform
.
android_arm64
;
}
else
{
_applicationPlatform
=
TargetPlatform
.
android_arm
;
}
break
;
case
'x86_64'
:
_applicationPlatform
=
TargetPlatform
.
android_x64
;
break
;
case
'x86'
:
_applicationPlatform
=
TargetPlatform
.
android_x86
;
break
;
default
:
_applicationPlatform
=
TargetPlatform
.
android_arm
;
break
;
}
late
final
Future
<
TargetPlatform
>
targetPlatform
=
()
async
{
// http://developer.android.com/ndk/guides/abis.html (x86, armeabi-v7a, ...)
switch
(
await
_getProperty
(
'ro.product.cpu.abi'
))
{
case
'arm64-v8a'
:
// Perform additional verification for 64 bit ABI. Some devices,
// like the Kindle Fire 8, misreport the abilist. We might not
// be able to retrieve this property, in which case we fall back
// to assuming 64 bit.
final
String
?
abilist
=
await
_getProperty
(
'ro.product.cpu.abilist'
);
if
(
abilist
==
null
||
abilist
.
contains
(
'arm64-v8a'
))
{
return
TargetPlatform
.
android_arm64
;
}
else
{
return
TargetPlatform
.
android_arm
;
}
case
'x86_64'
:
return
TargetPlatform
.
android_x64
;
case
'x86'
:
return
TargetPlatform
.
android_x86
;
default
:
return
TargetPlatform
.
android_arm
;
}
return
_applicationPlatform
;
}
}();
@override
Future
<
bool
>
supportsRuntimeMode
(
BuildMode
buildMode
)
async
{
...
...
@@ -249,28 +232,27 @@ class AndroidDevice extends Device {
case
TargetPlatform
.
windows_x64
:
throw
UnsupportedError
(
'Invalid target platform for Android'
);
}
throw
null
;
// dead code, remove after null migration
}
@override
Future
<
String
>
get
sdkNameAndVersion
async
=>
'Android
${await _sdkVersion}
(API
${await apiVersion}
)'
;
Future
<
String
>
get
_sdkVersion
=>
_getProperty
(
'ro.build.version.release'
);
Future
<
String
?
>
get
_sdkVersion
=>
_getProperty
(
'ro.build.version.release'
);
@visibleForTesting
Future
<
String
>
get
apiVersion
=>
_getProperty
(
'ro.build.version.sdk'
);
Future
<
String
?
>
get
apiVersion
=>
_getProperty
(
'ro.build.version.sdk'
);
AdbLogReader
_logReader
;
AdbLogReader
_pastLogReader
;
AndroidDevicePortForwarder
_portForwarder
;
AdbLogReader
?
_logReader
;
AdbLogReader
?
_pastLogReader
;
AndroidDevicePortForwarder
?
_portForwarder
;
List
<
String
>
adbCommandForDevice
(
List
<
String
>
args
)
{
return
<
String
>[
_androidSdk
.
adbPath
,
'-s'
,
id
,
...
args
];
return
<
String
>[
_androidSdk
.
adbPath
!
,
'-s'
,
id
,
...
args
];
}
Future
<
RunResult
>
runAdbCheckedAsync
(
List
<
String
>
params
,
{
String
workingDirectory
,
String
?
workingDirectory
,
bool
allowReentrantFlutter
=
false
,
})
async
{
return
_processUtils
.
run
(
...
...
@@ -284,11 +266,11 @@ class AndroidDevice extends Device {
bool
_isValidAdbVersion
(
String
adbVersion
)
{
// Sample output: 'Android Debug Bridge version 1.0.31'
final
Match
versionFields
=
RegExp
(
r'(\d+)\.(\d+)\.(\d+)'
).
firstMatch
(
adbVersion
);
final
Match
?
versionFields
=
RegExp
(
r'(\d+)\.(\d+)\.(\d+)'
).
firstMatch
(
adbVersion
);
if
(
versionFields
!=
null
)
{
final
int
majorVersion
=
int
.
parse
(
versionFields
[
1
]);
final
int
minorVersion
=
int
.
parse
(
versionFields
[
2
]);
final
int
patchVersion
=
int
.
parse
(
versionFields
[
3
]);
final
int
majorVersion
=
int
.
parse
(
versionFields
[
1
]
!
);
final
int
minorVersion
=
int
.
parse
(
versionFields
[
2
]
!
);
final
int
patchVersion
=
int
.
parse
(
versionFields
[
3
]
!
);
if
(
majorVersion
>
1
)
{
return
true
;
}
...
...
@@ -306,19 +288,20 @@ class AndroidDevice extends Device {
}
Future
<
bool
>
_checkForSupportedAdbVersion
()
async
{
if
(
_androidSdk
==
null
)
{
final
String
?
adbPath
=
_androidSdk
.
adbPath
;
if
(
adbPath
==
null
)
{
return
false
;
}
try
{
final
RunResult
adbVersion
=
await
_processUtils
.
run
(
<
String
>[
_androidSdk
.
adbPath
,
'version'
],
<
String
>[
adbPath
,
'version'
],
throwOnError:
true
,
);
if
(
_isValidAdbVersion
(
adbVersion
.
stdout
))
{
return
true
;
}
_logger
.
printError
(
'The ADB at "
$
{_androidSdk.adbPath}
" is too old; please install version 1.0.39 or later.'
);
_logger
.
printError
(
'The ADB at "
$
adbPath
" is too old; please install version 1.0.39 or later.'
);
}
on
Exception
catch
(
error
,
trace
)
{
_logger
.
printError
(
'Error running ADB:
$error
'
,
stackTrace:
trace
);
}
...
...
@@ -327,13 +310,17 @@ class AndroidDevice extends Device {
}
Future
<
bool
>
_checkForSupportedAndroidVersion
()
async
{
final
String
?
adbPath
=
_androidSdk
.
adbPath
;
if
(
adbPath
==
null
)
{
return
false
;
}
try
{
// If the server is automatically restarted, then we get irrelevant
// output lines like this, which we want to ignore:
// adb server is out of date. killing..
// * daemon started successfully *
await
_processUtils
.
run
(
<
String
>[
_androidSdk
.
adbPath
,
'start-server'
],
<
String
>[
adbPath
,
'start-server'
],
throwOnError:
true
,
);
...
...
@@ -343,7 +330,7 @@ class AndroidDevice extends Device {
final
String
sdkVersion
=
await
_getProperty
(
'ro.build.version.sdk'
)
??
minApiLevel
.
toString
();
final
int
sdkVersionParsed
=
int
.
tryParse
(
sdkVersion
);
final
int
?
sdkVersionParsed
=
int
.
tryParse
(
sdkVersion
);
if
(
sdkVersionParsed
==
null
)
{
_logger
.
printError
(
'Unexpected response from getprop: "
$sdkVersion
"'
);
return
false
;
...
...
@@ -385,7 +372,7 @@ class AndroidDevice extends Device {
@override
Future
<
bool
>
isAppInstalled
(
AndroidApk
app
,
{
String
userIdentifier
,
String
?
userIdentifier
,
})
async
{
// This call takes 400ms - 600ms.
try
{
...
...
@@ -414,9 +401,9 @@ class AndroidDevice extends Device {
@override
Future
<
bool
>
installApp
(
AndroidApk
app
,
{
String
userIdentifier
,
String
?
userIdentifier
,
})
async
{
if
(!
await
_
isAdbValid
()
)
{
if
(!
await
_
adbIsValid
)
{
return
false
;
}
final
bool
wasInstalled
=
await
isAppInstalled
(
app
,
userIdentifier:
userIdentifier
);
...
...
@@ -446,7 +433,7 @@ class AndroidDevice extends Device {
Future
<
bool
>
_installApp
(
AndroidApk
app
,
{
String
userIdentifier
,
String
?
userIdentifier
,
})
async
{
if
(!
app
.
file
.
existsSync
())
{
_logger
.
printError
(
'"
${_fileSystem.path.relative(app.file.path)}
" does not exist.'
);
...
...
@@ -469,7 +456,7 @@ class AndroidDevice extends Device {
// Some versions of adb exit with exit code 0 even on failure :(
// Parsing the output to check for failures.
final
RegExp
failureExp
=
RegExp
(
r'^Failure.*$'
,
multiLine:
true
);
final
String
failure
=
failureExp
.
stringMatch
(
installResult
.
stdout
);
final
String
?
failure
=
failureExp
.
stringMatch
(
installResult
.
stdout
);
if
(
failure
!=
null
)
{
_logger
.
printError
(
'Package install error:
$failure
'
);
return
false
;
...
...
@@ -497,9 +484,9 @@ class AndroidDevice extends Device {
@override
Future
<
bool
>
uninstallApp
(
AndroidApk
app
,
{
String
userIdentifier
,
String
?
userIdentifier
,
})
async
{
if
(!
await
_
isAdbValid
()
)
{
if
(!
await
_
adbIsValid
)
{
return
false
;
}
...
...
@@ -519,7 +506,7 @@ class AndroidDevice extends Device {
return
false
;
}
final
RegExp
failureExp
=
RegExp
(
r'^Failure.*$'
,
multiLine:
true
);
final
String
failure
=
failureExp
.
stringMatch
(
uninstallOut
);
final
String
?
failure
=
failureExp
.
stringMatch
(
uninstallOut
);
if
(
failure
!=
null
)
{
_logger
.
printError
(
'Package uninstall error:
$failure
'
);
return
false
;
...
...
@@ -528,25 +515,24 @@ class AndroidDevice extends Device {
}
// Whether the adb and Android versions are aligned.
bool
_adbIsValid
;
Future
<
bool
>
_isAdbValid
()
async
{
return
_adbIsValid
??=
await
_checkForSupportedAdbVersion
()
&&
await
_checkForSupportedAndroidVersion
();
}
late
final
Future
<
bool
>
_adbIsValid
=
()
async
{
return
await
_checkForSupportedAdbVersion
()
&&
await
_checkForSupportedAndroidVersion
();
}();
AndroidApk
_package
;
AndroidApk
?
_package
;
@override
Future
<
LaunchResult
>
startApp
(
AndroidApk
package
,
{
String
mainPath
,
String
route
,
DebuggingOptions
debuggingOptions
,
Map
<
String
,
dynamic
>
platformArgs
=
const
<
String
,
Object
>{},
String
?
mainPath
,
String
?
route
,
required
DebuggingOptions
debuggingOptions
,
Map
<
String
,
Object
?
>
platformArgs
=
const
<
String
,
Object
>{},
bool
prebuiltApplication
=
false
,
bool
ipv6
=
false
,
String
userIdentifier
,
String
?
userIdentifier
,
})
async
{
if
(!
await
_
isAdbValid
()
)
{
if
(!
await
_
adbIsValid
)
{
return
LaunchResult
.
failed
();
}
...
...
@@ -589,19 +575,19 @@ class AndroidDevice extends Device {
if
(!
prebuiltApplication
||
_androidSdk
.
licensesAvailable
&&
_androidSdk
.
latestVersion
==
null
)
{
_logger
.
printTrace
(
'Building APK'
);
final
FlutterProject
project
=
FlutterProject
.
current
();
await
androidBuilder
.
buildApk
(
await
androidBuilder
!
.
buildApk
(
project:
project
,
target:
mainPath
,
target:
mainPath
??
'lib/main.dart'
,
androidBuildInfo:
AndroidBuildInfo
(
debuggingOptions
.
buildInfo
,
targetArchs:
<
AndroidArch
>[
androidArch
],
fastStart:
debuggingOptions
.
fastStart
,
multidexEnabled:
(
platformArgs
[
'multidex'
]
as
bool
)
??
false
,
multidexEnabled:
(
platformArgs
[
'multidex'
]
as
bool
?
)
??
false
,
),
);
// Package has been built, so we can get the updated application ID and
// activity name from the .apk.
package
=
await
ApplicationPackageFactory
.
instance
package
=
await
ApplicationPackageFactory
.
instance
!
.
getPackageForPlatform
(
devicePlatform
,
buildInfo:
debuggingOptions
.
buildInfo
)
as
AndroidApk
;
}
// There was a failure parsing the android project information.
...
...
@@ -616,8 +602,8 @@ class AndroidDevice extends Device {
return
LaunchResult
.
failed
();
}
final
bool
traceStartup
=
platformArgs
[
'trace-startup'
]
as
bool
??
false
;
ProtocolDiscovery
observatoryDiscovery
;
final
bool
traceStartup
=
platformArgs
[
'trace-startup'
]
as
bool
?
??
false
;
ProtocolDiscovery
?
observatoryDiscovery
;
if
(
debuggingOptions
.
debuggingEnabled
)
{
observatoryDiscovery
=
ProtocolDiscovery
.
observatory
(
...
...
@@ -637,6 +623,8 @@ class AndroidDevice extends Device {
}
final
String
dartVmFlags
=
computeDartVmFlags
(
debuggingOptions
);
final
String
?
traceAllowlist
=
debuggingOptions
.
traceAllowlist
;
final
String
?
traceSkiaAllowlist
=
debuggingOptions
.
traceSkiaAllowlist
;
final
List
<
String
>
cmd
=
<
String
>[
'shell'
,
'am'
,
'start'
,
'-a'
,
'android.intent.action.RUN'
,
...
...
@@ -653,10 +641,10 @@ class AndroidDevice extends Device {
...<
String
>[
'--ez'
,
'skia-deterministic-rendering'
,
'true'
],
if
(
debuggingOptions
.
traceSkia
)
...<
String
>[
'--ez'
,
'trace-skia'
,
'true'
],
if
(
debuggingOptions
.
traceAllowlist
!=
null
)
...<
String
>[
'--es'
,
'trace-allowlist'
,
debuggingOptions
.
traceAllowlist
],
if
(
debuggingOptions
.
traceSkiaAllowlist
!=
null
)
...<
String
>[
'--es'
,
'trace-skia-allowlist'
,
debuggingOptions
.
traceSkiaAllowlist
],
if
(
traceAllowlist
!=
null
)
...<
String
>[
'--es'
,
'trace-allowlist'
,
traceAllowlist
],
if
(
traceSkiaAllowlist
!=
null
)
...<
String
>[
'--es'
,
'trace-skia-allowlist'
,
traceSkiaAllowlist
],
if
(
debuggingOptions
.
traceSystrace
)
...<
String
>[
'--ez'
,
'trace-systrace'
,
'true'
],
if
(
debuggingOptions
.
endlessTraceBuffer
)
...
...
@@ -703,9 +691,9 @@ class AndroidDevice extends Device {
// device has printed "Observatory is listening on...".
_logger
.
printTrace
(
'Waiting for observatory port to be available...'
);
try
{
Uri
observatoryUri
;
Uri
?
observatoryUri
;
if
(
debuggingOptions
.
buildInfo
.
isDebug
||
debuggingOptions
.
buildInfo
.
isProfile
)
{
observatoryUri
=
await
observatoryDiscovery
.
uri
;
observatoryUri
=
await
observatoryDiscovery
?
.
uri
;
if
(
observatoryUri
==
null
)
{
_logger
.
printError
(
'Error waiting for a debug connection: '
...
...
@@ -719,7 +707,7 @@ class AndroidDevice extends Device {
_logger
.
printError
(
'Error waiting for a debug connection:
$error
'
);
return
LaunchResult
.
failed
();
}
finally
{
await
observatoryDiscovery
.
cancel
();
await
observatoryDiscovery
?
.
cancel
();
}
}
...
...
@@ -735,7 +723,7 @@ class AndroidDevice extends Device {
@override
Future
<
bool
>
stopApp
(
AndroidApk
app
,
{
String
userIdentifier
,
String
?
userIdentifier
,
})
{
if
(
app
==
null
)
{
return
Future
<
bool
>.
value
(
false
);
...
...
@@ -754,11 +742,16 @@ class AndroidDevice extends Device {
@override
Future
<
MemoryInfo
>
queryMemoryInfo
()
async
{
final
AndroidApk
?
package
=
_package
;
if
(
package
==
null
)
{
_logger
.
printError
(
'Android package unknown, skipping dumpsys meminfo.'
);
return
const
MemoryInfo
.
empty
();
}
final
RunResult
runResult
=
await
_processUtils
.
run
(
adbCommandForDevice
(<
String
>[
'shell'
,
'dumpsys'
,
'meminfo'
,
_
package
.
id
,
package
.
id
,
'-d'
,
]));
...
...
@@ -775,7 +768,7 @@ class AndroidDevice extends Device {
@override
FutureOr
<
DeviceLogReader
>
getLogReader
({
AndroidApk
app
,
AndroidApk
?
app
,
bool
includePastLogs
=
false
,
})
async
{
// The Android log reader isn't app-specific. The `app` parameter isn't used.
...
...
@@ -794,19 +787,25 @@ class AndroidDevice extends Device {
}
@override
DevicePortForwarder
get
portForwarder
=>
_portForwarder
??=
AndroidDevicePortForwarder
(
processManager:
_processManager
,
logger:
_logger
,
deviceId:
id
,
adbPath:
_androidSdk
.
adbPath
,
);
late
final
DevicePortForwarder
?
portForwarder
=
()
{
final
String
?
adbPath
=
_androidSdk
.
adbPath
;
if
(
adbPath
==
null
)
{
return
null
;
}
return
AndroidDevicePortForwarder
(
processManager:
_processManager
,
logger:
_logger
,
deviceId:
id
,
adbPath:
adbPath
,
);
}();
static
final
RegExp
_timeRegExp
=
RegExp
(
r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}'
,
multiLine:
true
);
/// Return the most recent timestamp in the Android log or [null] if there is
/// no available timestamp. The format can be passed to logcat's -T option.
@visibleForTesting
Future
<
String
>
lastLogcatTimestamp
()
async
{
Future
<
String
?
>
lastLogcatTimestamp
()
async
{
RunResult
output
;
try
{
output
=
await
runAdbCheckedAsync
(<
String
>[
...
...
@@ -816,7 +815,7 @@ class AndroidDevice extends Device {
_logger
.
printError
(
'Failed to extract the most recent timestamp from the Android log:
$error
.'
);
return
null
;
}
final
Match
timeMatch
=
_timeRegExp
.
firstMatch
(
output
.
stdout
);
final
Match
?
timeMatch
=
_timeRegExp
.
firstMatch
(
output
.
stdout
);
return
timeMatch
?.
group
(
0
);
}
...
...
@@ -854,7 +853,7 @@ Map<String, String> parseAdbDeviceProperties(String str) {
final
Map
<
String
,
String
>
properties
=
<
String
,
String
>{};
final
RegExp
propertyExp
=
RegExp
(
r'\[(.*?)\]: \[(.*?)\]'
);
for
(
final
Match
match
in
propertyExp
.
allMatches
(
str
))
{
properties
[
match
.
group
(
1
)
]
=
match
.
group
(
2
)
;
properties
[
match
.
group
(
1
)
!]
=
match
.
group
(
2
)!
;
}
return
properties
;
}
...
...
@@ -1011,12 +1010,7 @@ class AndroidMemoryInfo extends MemoryInfo {
/// A log reader that logs from `adb logcat`.
class
AdbLogReader
extends
DeviceLogReader
{
AdbLogReader
.
_
(
this
.
_adbProcess
,
this
.
name
)
{
_linesController
=
StreamController
<
String
>.
broadcast
(
onListen:
_start
,
onCancel:
_stop
,
);
}
AdbLogReader
.
_
(
this
.
_adbProcess
,
this
.
name
);
@visibleForTesting
factory
AdbLogReader
.
test
(
Process
adbProcess
,
String
name
)
=
AdbLogReader
.
_
;
...
...
@@ -1029,7 +1023,7 @@ class AdbLogReader extends DeviceLogReader {
})
async
{
// logcat -T is not supported on Android releases before Lollipop.
const
int
kLollipopVersionCode
=
21
;
final
int
apiVersion
=
(
String
v
)
{
final
int
?
apiVersion
=
(
String
?
v
)
{
// If the API version string isn't found, conservatively assume that the
// version is less recent than the one we're looking for.
return
v
==
null
?
kLollipopVersionCode
-
1
:
int
.
tryParse
(
v
);
...
...
@@ -1052,7 +1046,7 @@ class AdbLogReader extends DeviceLogReader {
}
else
if
(
apiVersion
!=
null
&&
apiVersion
>=
kLollipopVersionCode
)
{
// Otherwise, filter for logs appearing past the present.
// '-T 0` means the timestamp of the logcat command invocation.
final
String
lastLogcatTimestamp
=
await
device
.
lastLogcatTimestamp
();
final
String
?
lastLogcatTimestamp
=
await
device
.
lastLogcatTimestamp
();
args
.
addAll
(<
String
>[
'-T'
,
if
(
lastLogcatTimestamp
!=
null
)
"'
$lastLogcatTimestamp
'"
else
'0'
,
...
...
@@ -1067,7 +1061,10 @@ class AdbLogReader extends DeviceLogReader {
@override
final
String
name
;
StreamController
<
String
>
_linesController
;
late
final
StreamController
<
String
>
_linesController
=
StreamController
<
String
>.
broadcast
(
onListen:
_start
,
onCancel:
_stop
,
);
@override
Stream
<
String
>
get
logLines
=>
_linesController
.
stream
;
...
...
@@ -1128,14 +1125,14 @@ class AdbLogReader extends DeviceLogReader {
if
(
_linesController
.
isClosed
)
{
return
;
}
final
Match
timeMatch
=
AndroidDevice
.
_timeRegExp
.
firstMatch
(
line
);
final
Match
?
timeMatch
=
AndroidDevice
.
_timeRegExp
.
firstMatch
(
line
);
if
(
timeMatch
==
null
||
line
.
length
==
timeMatch
.
end
)
{
_acceptedLastLine
=
false
;
return
;
}
// Chop off the time.
line
=
line
.
substring
(
timeMatch
.
end
+
1
);
final
Match
logMatch
=
_logFormat
.
firstMatch
(
line
);
final
Match
?
logMatch
=
_logFormat
.
firstMatch
(
line
);
if
(
logMatch
!=
null
)
{
bool
acceptLine
=
false
;
...
...
@@ -1143,19 +1140,19 @@ class AdbLogReader extends DeviceLogReader {
// While a fatal crash is going on, only accept lines from the crash
// Otherwise the crash log in the console may get interrupted
final
Match
fatalMatch
=
_tombstoneLine
.
firstMatch
(
line
);
final
Match
?
fatalMatch
=
_tombstoneLine
.
firstMatch
(
line
);
if
(
fatalMatch
!=
null
)
{
acceptLine
=
true
;
line
=
fatalMatch
[
1
];
line
=
fatalMatch
[
1
]
!
;
if
(
_tombstoneTerminator
.
hasMatch
(
fatalMatch
[
1
]
))
{
if
(
_tombstoneTerminator
.
hasMatch
(
line
))
{
// Hit crash terminator, stop logging the crash info
_fatalCrash
=
false
;
}
}
}
else
if
(
appPid
!=
null
&&
int
.
parse
(
logMatch
.
group
(
1
))
==
appPid
)
{
}
else
if
(
appPid
!=
null
&&
int
.
parse
(
logMatch
.
group
(
1
)
!
)
==
appPid
)
{
acceptLine
=
true
;
if
(
_fatalLog
.
hasMatch
(
line
))
{
...
...
@@ -1189,7 +1186,7 @@ class AdbLogReader extends DeviceLogReader {
void
_stop
()
{
_linesController
.
close
();
_adbProcess
?
.
kill
();
_adbProcess
.
kill
();
}
@override
...
...
@@ -1201,10 +1198,10 @@ class AdbLogReader extends DeviceLogReader {
/// A [DevicePortForwarder] implemented for Android devices that uses adb.
class
AndroidDevicePortForwarder
extends
DevicePortForwarder
{
AndroidDevicePortForwarder
({
@
required
ProcessManager
processManager
,
@
required
Logger
logger
,
@
required
String
deviceId
,
@
required
String
adbPath
,
required
ProcessManager
processManager
,
required
Logger
logger
,
required
String
deviceId
,
required
String
adbPath
,
})
:
_deviceId
=
deviceId
,
_adbPath
=
adbPath
,
_logger
=
logger
,
...
...
@@ -1215,7 +1212,7 @@ class AndroidDevicePortForwarder extends DevicePortForwarder {
final
Logger
_logger
;
final
ProcessUtils
_processUtils
;
static
int
_extractPort
(
String
portString
)
{
static
int
?
_extractPort
(
String
portString
)
{
return
int
.
tryParse
(
portString
.
trim
());
}
...
...
@@ -1253,8 +1250,8 @@ class AndroidDevicePortForwarder extends DevicePortForwarder {
}
// Attempt to extract ports.
final
int
hostPort
=
_extractPort
(
splitLine
[
1
]);
final
int
devicePort
=
_extractPort
(
splitLine
[
2
]);
final
int
?
hostPort
=
_extractPort
(
splitLine
[
1
]);
final
int
?
devicePort
=
_extractPort
(
splitLine
[
2
]);
// Failed, skip.
if
(
hostPort
==
null
||
devicePort
==
null
)
{
...
...
@@ -1268,7 +1265,7 @@ class AndroidDevicePortForwarder extends DevicePortForwarder {
}
@override
Future
<
int
>
forward
(
int
devicePort
,
{
int
hostPort
})
async
{
Future
<
int
>
forward
(
int
devicePort
,
{
int
?
hostPort
})
async
{
hostPort
??=
0
;
final
RunResult
process
=
await
_processUtils
.
run
(
<
String
>[
...
...
@@ -1320,7 +1317,7 @@ class AndroidDevicePortForwarder extends DevicePortForwarder {
}
}
return
hostPort
;
return
hostPort
!
;
}
@override
...
...
@@ -1335,7 +1332,6 @@ class AndroidDevicePortForwarder extends DevicePortForwarder {
'--remove'
,
tcpLine
,
],
throwOnError:
false
,
);
if
(
runResult
.
exitCode
==
0
)
{
return
;
...
...
packages/flutter_tools/lib/src/android/android_device_discovery.dart
View file @
0c9a4205
...
...
@@ -2,9 +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
'package:meta/meta.dart'
;
import
'package:process/process.dart'
;
import
'../base/common.dart'
;
...
...
@@ -29,13 +26,13 @@ import 'android_workflow.dart';
/// * [AndroidDevice], the type of discovered device.
class
AndroidDevices
extends
PollingDeviceDiscovery
{
AndroidDevices
({
@
required
AndroidWorkflow
androidWorkflow
,
@
required
ProcessManager
processManager
,
@
required
Logger
logger
,
@required
AndroidSdk
androidSdk
,
@
required
FileSystem
fileSystem
,
@
required
Platform
platform
,
@
required
UserMessages
userMessages
,
required
AndroidWorkflow
androidWorkflow
,
required
ProcessManager
processManager
,
required
Logger
logger
,
AndroidSdk
?
androidSdk
,
required
FileSystem
fileSystem
,
required
Platform
platform
,
required
UserMessages
userMessages
,
})
:
_androidWorkflow
=
androidWorkflow
,
_androidSdk
=
androidSdk
,
_processUtils
=
ProcessUtils
(
...
...
@@ -51,7 +48,7 @@ class AndroidDevices extends PollingDeviceDiscovery {
final
AndroidWorkflow
_androidWorkflow
;
final
ProcessUtils
_processUtils
;
final
AndroidSdk
_androidSdk
;
final
AndroidSdk
?
_androidSdk
;
final
ProcessManager
_processManager
;
final
Logger
_logger
;
final
FileSystem
_fileSystem
;
...
...
@@ -65,13 +62,13 @@ class AndroidDevices extends PollingDeviceDiscovery {
bool
get
canListAnything
=>
_androidWorkflow
.
canListDevices
;
@override
Future
<
List
<
Device
>>
pollingGetDevices
({
Duration
timeout
})
async
{
Future
<
List
<
Device
>>
pollingGetDevices
({
Duration
?
timeout
})
async
{
if
(
_doesNotHaveAdb
())
{
return
<
AndroidDevice
>[];
}
String
text
;
try
{
text
=
(
await
_processUtils
.
run
(<
String
>[
_androidSdk
.
adbPath
,
'devices'
,
'-l'
],
text
=
(
await
_processUtils
.
run
(<
String
>[
_androidSdk
!.
adbPath
!
,
'devices'
,
'-l'
],
throwOnError:
true
,
)).
stdout
.
trim
();
}
on
ProcessException
catch
(
exception
)
{
...
...
@@ -94,7 +91,7 @@ class AndroidDevices extends PollingDeviceDiscovery {
return
<
String
>[];
}
final
RunResult
result
=
await
_processUtils
.
run
(<
String
>[
_androidSdk
.
adbPath
,
'devices'
,
'-l'
]);
final
RunResult
result
=
await
_processUtils
.
run
(<
String
>[
_androidSdk
!.
adbPath
!
,
'devices'
,
'-l'
]);
if
(
result
.
exitCode
!=
0
)
{
return
<
String
>[];
}
...
...
@@ -108,8 +105,8 @@ class AndroidDevices extends PollingDeviceDiscovery {
bool
_doesNotHaveAdb
()
{
return
_androidSdk
==
null
||
_androidSdk
.
adbPath
==
null
||
!
_processManager
.
canRun
(
_androidSdk
.
adbPath
);
_androidSdk
?
.
adbPath
==
null
||
!
_processManager
.
canRun
(
_androidSdk
!
.
adbPath
);
}
// 015d172c98400a03 device usb:340787200X product:nakasi model:Nexus_7 device:grouper
...
...
@@ -120,8 +117,8 @@ class AndroidDevices extends PollingDeviceDiscovery {
/// in which case information for that parameter won't be populated.
void
_parseADBDeviceOutput
(
String
text
,
{
List
<
AndroidDevice
>
devices
,
List
<
String
>
diagnostics
,
List
<
AndroidDevice
>
?
devices
,
List
<
String
>
?
diagnostics
,
})
{
// Check for error messages from adb
if
(!
text
.
contains
(
'List of devices'
))
{
...
...
@@ -146,11 +143,11 @@ class AndroidDevices extends PollingDeviceDiscovery {
}
if
(
_kDeviceRegex
.
hasMatch
(
line
))
{
final
Match
match
=
_kDeviceRegex
.
firstMatch
(
line
);
final
Match
match
=
_kDeviceRegex
.
firstMatch
(
line
)
!
;
final
String
deviceID
=
match
[
1
];
final
String
deviceState
=
match
[
2
];
String
rest
=
match
[
3
];
final
String
deviceID
=
match
[
1
]
!
;
final
String
deviceState
=
match
[
2
]
!
;
String
rest
=
match
[
3
]
!
;
final
Map
<
String
,
String
>
info
=
<
String
,
String
>{};
if
(
rest
!=
null
&&
rest
.
isNotEmpty
)
{
...
...
@@ -163,8 +160,9 @@ class AndroidDevices extends PollingDeviceDiscovery {
}
}
if
(
info
[
'model'
]
!=
null
)
{
info
[
'model'
]
=
cleanAdbDeviceName
(
info
[
'model'
]);
final
String
?
model
=
info
[
'model'
];
if
(
model
!=
null
)
{
info
[
'model'
]
=
cleanAdbDeviceName
(
model
);
}
if
(
deviceState
==
'unauthorized'
)
{
...
...
@@ -180,7 +178,7 @@ class AndroidDevices extends PollingDeviceDiscovery {
productID:
info
[
'product'
],
modelID:
info
[
'model'
]
??
deviceID
,
deviceCodeName:
info
[
'device'
],
androidSdk:
_androidSdk
,
androidSdk:
_androidSdk
!
,
fileSystem:
_fileSystem
,
logger:
_logger
,
platform:
_platform
,
...
...
packages/flutter_tools/test/general.shard/android/adb_log_reader_test.dart
View file @
0c9a4205
...
...
@@ -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_device.dart'
;
...
...
@@ -183,7 +181,7 @@ void main() {
});
}
AndroidDevice
createFakeDevice
(
int
sdkLevel
)
{
AndroidDevice
createFakeDevice
(
int
?
sdkLevel
)
{
return
FakeAndroidDevice
(
sdkLevel
.
toString
(),
kLastLogcatTimestamp
,
...
...
packages/flutter_tools/test/general.shard/android/android_device_discovery_test.dart
View file @
0c9a4205
...
...
@@ -72,7 +72,6 @@ void main() {
testWithoutContext
(
'AndroidDevices returns empty device list and diagnostics on null Android SDK'
,
()
async
{
final
AndroidDevices
androidDevices
=
AndroidDevices
(
androidSdk:
null
,
logger:
BufferLogger
.
test
(),
androidWorkflow:
AndroidWorkflow
(
androidSdk:
FakeAndroidSdk
(
null
),
...
...
packages/flutter_tools/test/general.shard/android/android_device_port_forwarder_test.dart
View file @
0c9a4205
...
...
@@ -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
'package:flutter_tools/src/android/android_device.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/device_port_forwarder.dart'
;
...
...
packages/flutter_tools/test/general.shard/android/android_device_start_test.dart
View file @
0c9a4205
...
...
@@ -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
'package:file/memory.dart'
;
import
'package:flutter_tools/src/android/android_device.dart'
;
import
'package:flutter_tools/src/android/android_sdk.dart'
;
...
...
@@ -42,9 +40,9 @@ const FakeCommand kShaCommand = FakeCommand(
);
void
main
(
)
{
FileSystem
fileSystem
;
FakeProcessManager
processManager
;
AndroidSdk
androidSdk
;
late
FileSystem
fileSystem
;
late
FakeProcessManager
processManager
;
late
AndroidSdk
androidSdk
;
setUp
(()
{
processManager
=
FakeProcessManager
.
empty
();
...
...
packages/flutter_tools/test/general.shard/android/android_device_stop_test.dart
deleted
100644 → 0
View file @
53e04de6
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'package:file/memory.dart'
;
import
'package:flutter_tools/src/android/android_device.dart'
;
import
'package:flutter_tools/src/android/android_sdk.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/base/platform.dart'
;
import
'package:test/fake.dart'
;
import
'../../src/common.dart'
;
import
'../../src/fake_process_manager.dart'
;
void
main
(
)
{
testWithoutContext
(
'AndroidDevice.stopApp handles a null ApplicationPackage'
,
()
async
{
final
AndroidDevice
androidDevice
=
AndroidDevice
(
'1234'
,
androidSdk:
FakeAndroidSdk
(),
fileSystem:
MemoryFileSystem
.
test
(),
logger:
BufferLogger
.
test
(),
platform:
FakePlatform
(),
processManager:
FakeProcessManager
.
any
(),
);
expect
(
await
androidDevice
.
stopApp
(
null
),
false
);
});
}
class
FakeAndroidSdk
extends
Fake
implements
AndroidSdk
{
}
packages/flutter_tools/test/general.shard/android/android_device_test.dart
View file @
0c9a4205
...
...
@@ -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
'dart:convert'
;
import
'dart:typed_data'
;
...
...
@@ -459,15 +457,16 @@ Uptime: 441088659 Realtime: 521464097
}
AndroidDevice
setUpAndroidDevice
(
{
String
id
,
AndroidSdk
androidSdk
,
FileSystem
fileSystem
,
ProcessManager
processManager
,
Platform
platform
,
String
?
id
,
AndroidSdk
?
androidSdk
,
FileSystem
?
fileSystem
,
ProcessManager
?
processManager
,
Platform
?
platform
,
AndroidConsoleSocketFactory
androidConsoleSocketFactory
=
kAndroidConsoleSocketFactory
,
})
{
androidSdk
??=
FakeAndroidSdk
();
return
AndroidDevice
(
id
??
'1234'
,
modelID:
'TestModel'
,
logger:
BufferLogger
.
test
(),
platform:
platform
??
FakePlatform
(),
androidSdk:
androidSdk
,
...
...
packages/flutter_tools/test/general.shard/android/android_install_test.dart
View file @
0c9a4205
...
...
@@ -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
'package:file/memory.dart'
;
import
'package:flutter_tools/src/android/android_device.dart'
;
import
'package:flutter_tools/src/android/android_sdk.dart'
;
...
...
@@ -41,8 +39,8 @@ const FakeCommand kStoreShaCommand = FakeCommand(
);
void
main
(
)
{
FileSystem
fileSystem
;
BufferLogger
logger
;
late
FileSystem
fileSystem
;
late
BufferLogger
logger
;
setUp
(()
{
fileSystem
=
MemoryFileSystem
.
test
();
...
...
@@ -50,15 +48,16 @@ void main() {
});
AndroidDevice
setUpAndroidDevice
({
AndroidSdk
androidSdk
,
ProcessManager
processManager
,
AndroidSdk
?
androidSdk
,
ProcessManager
?
processManager
,
})
{
androidSdk
??=
FakeAndroidSdk
();
return
AndroidDevice
(
'1234'
,
modelID:
'TestModel'
,
logger:
logger
,
platform:
FakePlatform
(),
androidSdk:
androidSdk
,
fileSystem:
fileSystem
??
MemoryFileSystem
.
test
()
,
fileSystem:
fileSystem
,
processManager:
processManager
??
FakeProcessManager
.
any
(),
);
}
...
...
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