Send analytics on 'build ios' and 'build ipa' for plist impeller value (#135193)
This analytics event only records the value of the plist entry on `build` commands. This will give an idea of the proportion of users who are disabling Impeller when shipping apps.
This commit is contained in:
parent
c627dbfbc6
commit
30a9f99bc8
@ -20,6 +20,7 @@ import '../globals.dart' as globals;
|
|||||||
import '../ios/application_package.dart';
|
import '../ios/application_package.dart';
|
||||||
import '../ios/mac.dart';
|
import '../ios/mac.dart';
|
||||||
import '../ios/plist_parser.dart';
|
import '../ios/plist_parser.dart';
|
||||||
|
import '../reporting/reporting.dart';
|
||||||
import '../runner/flutter_command.dart';
|
import '../runner/flutter_command.dart';
|
||||||
import 'build.dart';
|
import 'build.dart';
|
||||||
|
|
||||||
@ -724,6 +725,21 @@ abstract class _BuildIOSSubCommand extends BuildSubCommand {
|
|||||||
if (result.output != null) {
|
if (result.output != null) {
|
||||||
globals.printStatus('Built ${result.output}.');
|
globals.printStatus('Built ${result.output}.');
|
||||||
|
|
||||||
|
// When an app is successfully built, record to analytics whether Impeller
|
||||||
|
// is enabled or disabled.
|
||||||
|
final BuildableIOSApp app = await buildableIOSApp;
|
||||||
|
final String plistPath = app.project.infoPlist.path;
|
||||||
|
final bool? impellerEnabled = globals.plistParser.getValueFromFile<bool>(
|
||||||
|
plistPath, PlistParser.kFLTEnableImpellerKey,
|
||||||
|
);
|
||||||
|
BuildEvent(
|
||||||
|
impellerEnabled == false
|
||||||
|
? 'plist-impeller-disabled'
|
||||||
|
: 'plist-impeller-enabled',
|
||||||
|
type: 'ios',
|
||||||
|
flutterUsage: globals.flutterUsage,
|
||||||
|
).send();
|
||||||
|
|
||||||
return FlutterCommandResult.success();
|
return FlutterCommandResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ class PlistParser {
|
|||||||
static const String kCFBundleVersionKey = 'CFBundleVersion';
|
static const String kCFBundleVersionKey = 'CFBundleVersion';
|
||||||
static const String kCFBundleDisplayNameKey = 'CFBundleDisplayName';
|
static const String kCFBundleDisplayNameKey = 'CFBundleDisplayName';
|
||||||
static const String kCFBundleNameKey = 'CFBundleName';
|
static const String kCFBundleNameKey = 'CFBundleName';
|
||||||
|
static const String kFLTEnableImpellerKey = 'FLTEnableImpeller';
|
||||||
static const String kMinimumOSVersionKey = 'MinimumOSVersion';
|
static const String kMinimumOSVersionKey = 'MinimumOSVersion';
|
||||||
static const String kNSPrincipalClassKey = 'NSPrincipalClass';
|
static const String kNSPrincipalClassKey = 'NSPrincipalClass';
|
||||||
|
|
||||||
|
@ -17,7 +17,9 @@ import 'package:flutter_tools/src/commands/build.dart';
|
|||||||
import 'package:flutter_tools/src/commands/build_ios.dart';
|
import 'package:flutter_tools/src/commands/build_ios.dart';
|
||||||
import 'package:flutter_tools/src/ios/code_signing.dart';
|
import 'package:flutter_tools/src/ios/code_signing.dart';
|
||||||
import 'package:flutter_tools/src/ios/mac.dart';
|
import 'package:flutter_tools/src/ios/mac.dart';
|
||||||
|
import 'package:flutter_tools/src/ios/plist_parser.dart';
|
||||||
import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
||||||
|
import 'package:flutter_tools/src/project.dart';
|
||||||
import 'package:flutter_tools/src/reporting/reporting.dart';
|
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||||
import 'package:test/fake.dart';
|
import 'package:test/fake.dart';
|
||||||
|
|
||||||
@ -438,6 +440,133 @@ void main() {
|
|||||||
Usage: () => usage,
|
Usage: () => usage,
|
||||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
|
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('Analytics for impeller plist setting', () {
|
||||||
|
const String plistContents = '''
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>FLTEnableImpeller</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
''';
|
||||||
|
const FakeCommand plutilCommand = FakeCommand(
|
||||||
|
command: <String>[
|
||||||
|
'/usr/bin/plutil', '-convert', 'xml1', '-o', '-', '/ios/Runner/Info.plist',
|
||||||
|
],
|
||||||
|
stdout: plistContents,
|
||||||
|
);
|
||||||
|
|
||||||
|
testUsingContext('Sends an analytics event when Impeller is enabled', () async {
|
||||||
|
final BuildCommand command = BuildCommand(
|
||||||
|
androidSdk: FakeAndroidSdk(),
|
||||||
|
buildSystem: TestBuildSystem.all(BuildResult(success: true)),
|
||||||
|
fileSystem: MemoryFileSystem.test(),
|
||||||
|
logger: BufferLogger.test(),
|
||||||
|
osUtils: FakeOperatingSystemUtils(),
|
||||||
|
);
|
||||||
|
createMinimalMockProjectFiles();
|
||||||
|
|
||||||
|
await createTestCommandRunner(command).run(
|
||||||
|
const <String>['build', 'ios', '--no-pub']
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(usage.events, contains(
|
||||||
|
const TestUsageEvent(
|
||||||
|
'build', 'ios',
|
||||||
|
label:'plist-impeller-enabled',
|
||||||
|
parameters:CustomDimensions(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
FileSystem: () => fileSystem,
|
||||||
|
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||||
|
xattrCommand,
|
||||||
|
setUpFakeXcodeBuildHandler(onRun: () {
|
||||||
|
fileSystem.directory('build/ios/Release-iphoneos/Runner.app')
|
||||||
|
.createSync(recursive: true);
|
||||||
|
}),
|
||||||
|
setUpRsyncCommand(onRun: () =>
|
||||||
|
fileSystem.file('build/ios/iphoneos/Runner.app/Frameworks/App.framework/App')
|
||||||
|
..createSync(recursive: true)
|
||||||
|
..writeAsBytesSync(List<int>.generate(10000, (int index) => 0))),
|
||||||
|
]),
|
||||||
|
Platform: () => macosPlatform,
|
||||||
|
FileSystemUtils: () => FileSystemUtils(
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
platform: macosPlatform,
|
||||||
|
),
|
||||||
|
Usage: () => usage,
|
||||||
|
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('Sends an analytics event when Impeller is disabled', () async {
|
||||||
|
final BuildCommand command = BuildCommand(
|
||||||
|
androidSdk: FakeAndroidSdk(),
|
||||||
|
buildSystem: TestBuildSystem.all(BuildResult(success: true)),
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
logger: BufferLogger.test(),
|
||||||
|
osUtils: FakeOperatingSystemUtils(),
|
||||||
|
);
|
||||||
|
createMinimalMockProjectFiles();
|
||||||
|
|
||||||
|
fileSystem.file(
|
||||||
|
fileSystem.path.join('usr', 'bin', 'plutil'),
|
||||||
|
).createSync(recursive: true);
|
||||||
|
|
||||||
|
final File infoPlist = fileSystem.file(fileSystem.path.join(
|
||||||
|
'ios', 'Runner', 'Info.plist',
|
||||||
|
))..createSync(recursive: true);
|
||||||
|
|
||||||
|
infoPlist.writeAsStringSync(plistContents);
|
||||||
|
|
||||||
|
await createTestCommandRunner(command).run(
|
||||||
|
const <String>['build', 'ios', '--no-pub']
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(usage.events, contains(
|
||||||
|
const TestUsageEvent(
|
||||||
|
'build', 'ios',
|
||||||
|
label:'plist-impeller-disabled',
|
||||||
|
parameters:CustomDimensions(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
FileSystem: () => fileSystem,
|
||||||
|
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||||
|
xattrCommand,
|
||||||
|
setUpFakeXcodeBuildHandler(onRun: () {
|
||||||
|
fileSystem.directory('build/ios/Release-iphoneos/Runner.app')
|
||||||
|
.createSync(recursive: true);
|
||||||
|
}),
|
||||||
|
setUpRsyncCommand(onRun: () =>
|
||||||
|
fileSystem.file('build/ios/iphoneos/Runner.app/Frameworks/App.framework/App')
|
||||||
|
..createSync(recursive: true)
|
||||||
|
..writeAsBytesSync(List<int>.generate(10000, (int index) => 0))),
|
||||||
|
]),
|
||||||
|
Platform: () => macosPlatform,
|
||||||
|
FileSystemUtils: () => FileSystemUtils(
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
platform: macosPlatform,
|
||||||
|
),
|
||||||
|
Usage: () => usage,
|
||||||
|
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
|
||||||
|
FlutterProjectFactory: () => FlutterProjectFactory(
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
logger: BufferLogger.test(),
|
||||||
|
),
|
||||||
|
PlistParser: () => PlistParser(
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
logger: BufferLogger.test(),
|
||||||
|
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||||
|
plutilCommand, plutilCommand, plutilCommand,
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
group('xcresults device', () {
|
group('xcresults device', () {
|
||||||
testUsingContext('Trace error if xcresult is empty.', () async {
|
testUsingContext('Trace error if xcresult is empty.', () async {
|
||||||
final BuildCommand command = BuildCommand(
|
final BuildCommand command = BuildCommand(
|
||||||
|
@ -63,7 +63,8 @@ class FakePlistUtils extends Fake implements PlistParser {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
T? getValueFromFile<T>(String plistFilePath, String key) {
|
T? getValueFromFile<T>(String plistFilePath, String key) {
|
||||||
return fileContents[plistFilePath]![key] as T?;
|
final Map<String, Object>? plistFile = fileContents[plistFilePath];
|
||||||
|
return plistFile == null ? null : plistFile[key] as T?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user