Skip to content

Commit 37a36fa

Browse files
authored
Fixes (#7419)
* Restores ML Pods after M77. * Fix Package.swift * Re-add catalyst to GHA workflow. * Restrict multiple model info and model downloads; fix modelPath check + minor fixes. * Replace static property for downloadStatus. * Add TODO for merging requests. * Add .notStarted download status and move TODO.
1 parent fbdac23 commit 37a36fa

File tree

5 files changed

+41
-8
lines changed

5 files changed

+41
-8
lines changed

FirebaseMLModelDownloader/Apps/Sample/MLDownloaderTestApp.xcodeproj/project.pbxproj

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,8 +633,10 @@
633633
buildSettings = {
634634
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
635635
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
636-
CODE_SIGN_STYLE = Automatic;
636+
CODE_SIGN_IDENTITY = "iPhone Developer";
637+
CODE_SIGN_STYLE = Manual;
637638
DEVELOPMENT_ASSET_PATHS = "\"MLDownloaderTestApp/Preview Content\"";
639+
DEVELOPMENT_TEAM = EQHXZ8M8AV;
638640
ENABLE_PREVIEWS = YES;
639641
INFOPLIST_FILE = MLDownloaderTestApp/Info.plist;
640642
LD_RUNPATH_SEARCH_PATHS = (
@@ -643,6 +645,7 @@
643645
);
644646
PRODUCT_BUNDLE_IDENTIFIER = com.google.MLDownloaderTestApp;
645647
PRODUCT_NAME = "$(TARGET_NAME)";
648+
PROVISIONING_PROFILE_SPECIFIER = "Google Development";
646649
SWIFT_VERSION = 5.0;
647650
TARGETED_DEVICE_FAMILY = "1,2";
648651
};
@@ -654,8 +657,10 @@
654657
buildSettings = {
655658
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
656659
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
657-
CODE_SIGN_STYLE = Automatic;
660+
CODE_SIGN_IDENTITY = "iPhone Developer";
661+
CODE_SIGN_STYLE = Manual;
658662
DEVELOPMENT_ASSET_PATHS = "\"MLDownloaderTestApp/Preview Content\"";
663+
DEVELOPMENT_TEAM = EQHXZ8M8AV;
659664
ENABLE_PREVIEWS = YES;
660665
INFOPLIST_FILE = MLDownloaderTestApp/Info.plist;
661666
LD_RUNPATH_SEARCH_PATHS = (
@@ -664,6 +669,7 @@
664669
);
665670
PRODUCT_BUNDLE_IDENTIFIER = com.google.MLDownloaderTestApp;
666671
PRODUCT_NAME = "$(TARGET_NAME)";
672+
PROVISIONING_PROFILE_SPECIFIER = "Google Development";
667673
SWIFT_VERSION = 5.0;
668674
TARGETED_DEVICE_FAMILY = "1,2";
669675
};

FirebaseMLModelDownloader/Apps/Sample/MLDownloaderTestApp/AppDelegate.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
2323
.LaunchOptionsKey: Any]?) -> Bool {
2424
// Override point for customization after application launch.
2525
FirebaseApp.configure()
26+
FirebaseConfiguration.shared.setLoggerLevel(.debug)
2627
return true
2728
}
2829

FirebaseMLModelDownloader/Sources/ModelDownloadTask.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class ModelDownloadTask: NSObject {
4343
/// User defaults to which local model info should ultimately be written.
4444
private let defaults: UserDefaults
4545
/// Keeps track of download associated with this model download task.
46-
private(set) var downloadStatus: ModelDownloadStatus
46+
private(set) var downloadStatus: ModelDownloadStatus = .notStarted
4747
/// Downloader instance.
4848
private let downloader: FileDownloader
4949
/// Telemetry logger.
@@ -59,19 +59,18 @@ class ModelDownloadTask: NSObject {
5959
self.downloader = downloader
6060
self.telemetryLogger = telemetryLogger
6161
self.defaults = defaults
62-
downloadStatus = .notStarted
6362
}
6463
}
6564

6665
extension ModelDownloadTask {
6766
/// Name for model file stored on device.
6867
var downloadedModelFileName: String {
69-
return "fbml_model__\(appName)__\(remoteModelInfo.name)"
68+
return "fbml_model__\(appName)__\(remoteModelInfo.name).tflite"
7069
}
7170

7271
func download(progressHandler: ProgressHandler?, completion: @escaping Completion) {
7372
/// Prevent multiple concurrent downloads.
74-
guard downloadStatus == .notStarted else {
73+
guard downloadStatus != .inProgress else {
7574
DeviceLogger.logEvent(level: .debug,
7675
message: ModelDownloadTask.ErrorDescription.anotherDownloadInProgress,
7776
messageCode: .anotherDownloadInProgressError)
@@ -85,12 +84,14 @@ extension ModelDownloadTask {
8584
telemetryLogger?.logModelDownloadEvent(eventName: .modelDownload,
8685
status: .downloading,
8786
downloadErrorCode: .noError)
87+
downloadStatus = .inProgress
8888
downloader.downloadFile(with: remoteModelInfo.downloadURL,
8989
progressHandler: { downloadedBytes, totalBytes in
9090
/// Fraction of model file downloaded.
9191
let calculatedProgress = Float(downloadedBytes) / Float(totalBytes)
9292
progressHandler?(calculatedProgress)
9393
}) { result in
94+
self.downloadStatus = .complete
9495
switch result {
9596
case let .success(response):
9697
DeviceLogger.logEvent(level: .debug,
@@ -147,7 +148,6 @@ extension ModelDownloadTask {
147148

148149
/// Handle model download response.
149150
func handleResponse(response: HTTPURLResponse, tempURL: URL, completion: @escaping Completion) {
150-
downloadStatus = .complete
151151
guard (200 ..< 299).contains(response.statusCode) else {
152152
switch response.statusCode {
153153
/// Possible failure due to download URL expiry.

FirebaseMLModelDownloader/Sources/ModelDownloader.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,8 @@ public class ModelDownloader {
248248
mainQueueHandler(completion(.failure(.internalError(description: description))))
249249
return
250250
}
251-
guard modelInfo.path == path.absoluteString else {
251+
guard let pathURL = URL(string: modelInfo.path)?.standardizedFileURL,
252+
pathURL == path.standardizedFileURL else {
252253
DeviceLogger.logEvent(level: .debug,
253254
message: ModelDownloader.ErrorDescription.outdatedModelPath,
254255
messageCode: .outdatedModelPathError)
@@ -377,6 +378,7 @@ extension ModelDownloader {
377378
progressHandler: ((Float) -> Void)? = nil,
378379
completion: @escaping (Result<CustomModel, DownloadError>)
379380
-> Void) {
381+
// TODO: Merge if there are multiple same requests.
380382
modelInfoRetriever.downloadModelInfo { result in
381383
switch result {
382384
case let .success(downloadModelInfoResult):

FirebaseMLModelDownloader/Sources/ModelInfoRetriever.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ import Foundation
1616
import FirebaseCore
1717
import FirebaseInstallations
1818

19+
/// Possible states of model downloading.
20+
enum ModelInfoDownloadStatus {
21+
case notStarted
22+
case inProgress
23+
case complete
24+
}
25+
1926
/// URL Session to use while retrieving model info.
2027
protocol ModelInfoRetrieverSession {
2128
func getModelInfo(with request: URLRequest,
@@ -76,6 +83,8 @@ class ModelInfoRetriever {
7683
private let apiKey: String
7784
/// Current Firebase app name.
7885
private let appName: String
86+
/// Keeps track of download associated with this model download task.
87+
private(set) var downloadStatus: ModelInfoDownloadStatus = .notStarted
7988
/// Local model info to validate model freshness.
8089
private let localModelInfo: LocalModelInfo?
8190
/// Telemetry logger.
@@ -144,6 +153,18 @@ class ModelInfoRetriever {
144153
/// Get model info from server.
145154
func downloadModelInfo(completion: @escaping (Result<DownloadModelInfoResult, DownloadError>)
146155
-> Void) {
156+
/// Prevent multiple concurrent downloads.
157+
guard downloadStatus != .inProgress else {
158+
DeviceLogger.logEvent(level: .debug,
159+
message: ModelInfoRetriever.ErrorDescription.anotherDownloadInProgress,
160+
messageCode: .anotherDownloadInProgressError)
161+
telemetryLogger?.logModelDownloadEvent(eventName: .modelDownload,
162+
status: .failed,
163+
downloadErrorCode: .downloadFailed)
164+
completion(.failure(.internalError(description: ModelInfoRetriever.ErrorDescription
165+
.anotherDownloadInProgress)))
166+
return
167+
}
147168
authTokenProvider { result in
148169
switch result {
149170
/// Successfully received FIS token.
@@ -165,9 +186,11 @@ class ModelInfoRetriever {
165186
.invalidModelInfoFetchURL)))
166187
return
167188
}
189+
self.downloadStatus = .inProgress
168190
/// Download model info.
169191
self.session.getModelInfo(with: request) {
170192
data, response, error in
193+
self.downloadStatus = .complete
171194
if let downloadError = error {
172195
let description = ModelInfoRetriever.ErrorDescription
173196
.failedModelInfoRetrieval(downloadError.localizedDescription)
@@ -478,5 +501,6 @@ extension ModelInfoRetriever {
478501
"Invalid download URL expiry time from server."
479502
static let modelHashMismatch = "Unexpected model hash value."
480503
static let permissionDenied = "Invalid or missing permissions to retrieve model info."
504+
static let anotherDownloadInProgress = "Model info download already in progress."
481505
}
482506
}

0 commit comments

Comments
 (0)