Browse Source

vm: add background mode using location tracking

Resolves #201
osy 5 năm trước cách đây
mục cha
commit
012906b088

+ 28 - 0
Managers/UTMLocationManager.h

@@ -0,0 +1,28 @@
+//
+// Copyright © 2020 osy. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface UTMLocationManager : NSObject
+
++ (instancetype)sharedInstance;
+- (void)startUpdatingLocation;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 61 - 0
Managers/UTMLocationManager.m

@@ -0,0 +1,61 @@
+//
+// Copyright © 2020 osy. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "UTMLocationManager.h"
+@import CoreLocation;
+
+@interface UTMLocationManager () <CLLocationManagerDelegate>
+
+@property (nonatomic) CLLocationManager *locationManager;
+
+@end
+
+@implementation UTMLocationManager
+
++ (instancetype)sharedInstance {
+    static id sharedInstance = nil;
+
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        sharedInstance = [[self alloc] init];
+        UTMLocationManager *instance = sharedInstance;
+        instance.locationManager = [[CLLocationManager alloc] init];
+        instance.locationManager.delegate = instance;
+        instance.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
+        instance.locationManager.pausesLocationUpdatesAutomatically = NO;
+    });
+
+    return sharedInstance;
+}
+
+- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
+    CLLocation *mostRecentLocation = locations.lastObject;
+    NSLog(@"Current location: %@ %@", @(mostRecentLocation.coordinate.latitude), @(mostRecentLocation.coordinate.longitude));
+}
+
+- (void)startUpdatingLocation {
+    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
+
+    if (status == kCLAuthorizationStatusDenied) {
+        NSLog(@"Location services are disabled in settings.");
+    } else {
+        [self.locationManager requestAlwaysAuthorization];
+        self.locationManager.allowsBackgroundLocationUpdates = YES;
+        [self.locationManager startUpdatingLocation];
+    }
+}
+
+@end

+ 6 - 0
UTM.xcodeproj/project.pbxproj

@@ -15,6 +15,7 @@
 		CE059DC1243BD67200338317 /* libphodav-2.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CE059DC0243BD67100338317 /* libphodav-2.0.0.dylib */; };
 		CE059DC2243BD67200338317 /* libphodav-2.0.0.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = CE059DC0243BD67100338317 /* libphodav-2.0.0.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		CE059DC5243BFA3200338317 /* UTMConfiguration+Sharing.m in Sources */ = {isa = PBXBuildFile; fileRef = CE059DC4243BFA3200338317 /* UTMConfiguration+Sharing.m */; };
+		CE059DC8243E9E3400338317 /* UTMLocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CE059DC7243E9E3400338317 /* UTMLocationManager.m */; };
 		CE23C16123FCEC0A001177D6 /* qapi-commands-run-state.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C07E23FCEBFF001177D6 /* qapi-commands-run-state.c */; };
 		CE23C16223FCEC0A001177D6 /* qapi-visit-tpm.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C07F23FCEBFF001177D6 /* qapi-visit-tpm.c */; };
 		CE23C16323FCEC0A001177D6 /* qapi-commands-rocker.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C08123FCEBFF001177D6 /* qapi-commands-rocker.c */; };
@@ -427,6 +428,8 @@
 		CE059DC0243BD67100338317 /* libphodav-2.0.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libphodav-2.0.0.dylib"; path = "sysroot-$(PLATFORM_PREFERRED_ARCH)/lib/libphodav-2.0.0.dylib"; sourceTree = "<group>"; };
 		CE059DC3243BFA3200338317 /* UTMConfiguration+Sharing.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UTMConfiguration+Sharing.h"; sourceTree = "<group>"; };
 		CE059DC4243BFA3200338317 /* UTMConfiguration+Sharing.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UTMConfiguration+Sharing.m"; sourceTree = "<group>"; };
+		CE059DC6243E9E3400338317 /* UTMLocationManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UTMLocationManager.h; sourceTree = "<group>"; };
+		CE059DC7243E9E3400338317 /* UTMLocationManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UTMLocationManager.m; sourceTree = "<group>"; };
 		CE23C07B23FCEBFF001177D6 /* qapi-visit-error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "qapi-visit-error.h"; path = "sysroot-$(PLATFORM_PREFERRED_ARCH)/qapi/qapi-visit-error.h"; sourceTree = SOURCE_ROOT; };
 		CE23C07C23FCEBFF001177D6 /* qapi-events-machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "qapi-events-machine.h"; path = "sysroot-$(PLATFORM_PREFERRED_ARCH)/qapi/qapi-events-machine.h"; sourceTree = SOURCE_ROOT; };
 		CE23C07D23FCEBFF001177D6 /* qapi-commands-block-core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "qapi-commands-block-core.h"; path = "sysroot-$(PLATFORM_PREFERRED_ARCH)/qapi/qapi-commands-block-core.h"; sourceTree = SOURCE_ROOT; };
@@ -1476,6 +1479,8 @@
 				E2D64BE0241EAEBE0034E0C6 /* UTMSpiceIODelegate.h */,
 				E2D64BCA241DB62A0034E0C6 /* UTMTerminalIO.h */,
 				E2D64BCB241DB62A0034E0C6 /* UTMTerminalIO.m */,
+				CE059DC6243E9E3400338317 /* UTMLocationManager.h */,
+				CE059DC7243E9E3400338317 /* UTMLocationManager.m */,
 			);
 			path = Managers;
 			sourceTree = "<group>";
@@ -1809,6 +1814,7 @@
 				CE23C1A223FCEC0A001177D6 /* qapi-types-ui.c in Sources */,
 				CE23C1B723FCEC0A001177D6 /* qapi-types-dump.c in Sources */,
 				CE23C1CC23FCEC0A001177D6 /* qapi-types-machine-target.c in Sources */,
+				CE059DC8243E9E3400338317 /* UTMLocationManager.m in Sources */,
 				CE23C1B223FCEC0A001177D6 /* qapi-events-block.c in Sources */,
 				CEBCAF4E243525DB00C2B423 /* VMConfigTextField.m in Sources */,
 				CE23C16E23FCEC0A001177D6 /* qapi-types-block-core.c in Sources */,

+ 21 - 11
UTM/Info.plist

@@ -2,11 +2,6 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
-	<key>NSAppTransportSecurity</key>
-	<dict>
-		<key>NSAllowsArbitraryLoads</key>
-		<true/>
-	</dict>
 	<key>CFBundleDevelopmentRegion</key>
 	<string>$(DEVELOPMENT_LANGUAGE)</string>
 	<key>CFBundleDocumentTypes</key>
@@ -46,6 +41,25 @@
 	<true/>
 	<key>LSSupportsOpeningDocumentsInPlace</key>
 	<true/>
+	<key>NSAppTransportSecurity</key>
+	<dict>
+		<key>NSAllowsArbitraryLoads</key>
+		<true/>
+	</dict>
+	<key>NSMicrophoneUsageDescription</key>
+	<string>VM needs access to microphone.</string>
+	<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
+	<string>VM background access requires location services. Location data will never leave the device.</string>
+	<key>NSLocationWhenInUseUsageDescription</key>
+	<string>VM background access requires location services. Location data will never leave the device.</string>
+	<key>NSLocationAlwaysUsageDescription</key>
+	<string>VM background access requires location services. Location data will never leave the device.</string>
+	<key>UIApplicationSupportsIndirectInputEvents</key>
+	<true/>
+	<key>UIBackgroundModes</key>
+	<array>
+		<string>location</string>
+	</array>
 	<key>UIFileSharingEnabled</key>
 	<true/>
 	<key>UILaunchStoryboardName</key>
@@ -69,6 +83,8 @@
 		<string>UIInterfaceOrientationLandscapeLeft</string>
 		<string>UIInterfaceOrientationLandscapeRight</string>
 	</array>
+	<key>UIViewControllerBasedStatusBarAppearance</key>
+	<true/>
 	<key>UTExportedTypeDeclarations</key>
 	<array>
 		<dict>
@@ -91,11 +107,5 @@
 			</dict>
 		</dict>
 	</array>
-	<key>UIViewControllerBasedStatusBarAppearance</key>
-	<true/>
-	<key>UIApplicationSupportsIndirectInputEvents</key>
-	<true/>
-	<key>NSMicrophoneUsageDescription</key>
-	<string>VM needs access to microphone.</string>
 </dict>
 </plist>

+ 11 - 1
UTM/Settings.bundle/Root.plist

@@ -10,7 +10,17 @@
 			<key>Type</key>
 			<string>PSGroupSpecifier</string>
 			<key>Title</key>
-			<string>Autosave</string>
+			<string>Background</string>
+		</dict>
+		<dict>
+			<key>Type</key>
+			<string>PSToggleSwitchSpecifier</string>
+			<key>Title</key>
+			<string>Continue running VM in the background</string>
+			<key>Key</key>
+			<string>RunInBackground</string>
+			<key>DefaultValue</key>
+			<false/>
 		</dict>
 		<dict>
 			<key>Type</key>

+ 1 - 0
Views/VMDisplayMetalViewController.h

@@ -75,6 +75,7 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, readonly) BOOL serverModeCursor;
 @property (nonatomic, readonly) BOOL autosaveBackground;
 @property (nonatomic, readonly) BOOL autosaveLowMemory;
+@property (nonatomic, readonly) BOOL runInBackground;
 
 - (void)sendExtendedKey:(SendKeyType)type code:(int)code;
 

+ 9 - 0
Views/VMDisplayMetalViewController.m

@@ -28,6 +28,7 @@
 #import "UTMConfiguration.h"
 #import "CSDisplayMetal.h"
 #import "UTMSpiceIO.h"
+#import "UTMLocationManager.h"
 
 @interface VMDisplayMetalViewController ()
 
@@ -84,6 +85,10 @@
     return [self boolForSetting:@"AutosaveLowMemory"];
 }
 
+- (BOOL)runInBackground {
+    return [self boolForSetting:@"RunInBackground"];
+}
+
 - (void)viewDidLoad {
     [super viewDidLoad];
     
@@ -147,6 +152,10 @@
 
 - (void)viewDidAppear:(BOOL)animated {
     [super viewDidAppear:animated];
+    if (self.runInBackground) {
+        NSLog(@"Start location tracking to enable running in background");
+        [[UTMLocationManager sharedInstance] startUpdatingLocation];
+    }
     if (self.vm.state == kVMStopped || self.vm.state == kVMSuspended) {
         [self.vm startVM];
         NSAssert([[self.vm ioService] isKindOfClass: [UTMSpiceIO class]], @"VM ioService must be UTMSpiceIO, but is: %@!", NSStringFromClass([[self.vm ioService] class]));

+ 13 - 0
Views/VMTerminalViewController.m

@@ -20,6 +20,7 @@
 #import "WKWebView+Workarounds.h"
 #import "VMKeyboardView.h"
 #import <CoreGraphics/CoreGraphics.h>
+#import "UTMLocationManager.h"
 
 NSString *const kVMSendInputHandler = @"UTMSendInput";
 NSString* const kVMDebugHandler = @"UTMDebug";
@@ -61,6 +62,10 @@ NSString* const kVMDebugHandler = @"UTMDebug";
     return YES; // always hide home indicator
 }
 
+- (BOOL)runInBackground {
+    return [self boolForSetting:@"RunInBackground"];
+}
+
 - (void)viewDidLoad {
     [super viewDidLoad];
     // UI setup
@@ -105,6 +110,14 @@ NSString* const kVMDebugHandler = @"UTMDebug";
     [self.navigationController setNavigationBarHidden:NO animated:animated];
 }
 
+- (void)viewDidAppear:(BOOL)animated {
+    [super viewDidAppear:animated];
+    if (self.runInBackground) {
+        NSLog(@"Start location tracking to enable running in background");
+        [[UTMLocationManager sharedInstance] startUpdatingLocation];
+    }
+}
+
 #pragma mark - Input accessory view
 
 - (IBAction)customKeyTouchDown:(VMKeyboardButton *)sender {