From f790db8534240cecbfdba6bfd3b1c52b1262d777 Mon Sep 17 00:00:00 2001 From: Dave Hylands Date: Wed, 30 Jan 2013 17:23:51 -0800 Subject: [PATCH] Bug 835210 - FOTA updates don't seem to be working any more. r=fabrice --- b2g/components/DirectoryProvider.js | 38 ++++++++++++++++++----------- b2g/components/RecoveryService.js | 9 +++++-- b2g/components/UpdatePrompt.js | 12 ++++++--- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/b2g/components/DirectoryProvider.js b/b2g/components/DirectoryProvider.js index bb4c1a8e1dd3..15602411ddc4 100644 --- a/b2g/components/DirectoryProvider.js +++ b/b2g/components/DirectoryProvider.js @@ -13,6 +13,8 @@ Cu.import("resource://gre/modules/Services.jsm"); const XRE_OS_UPDATE_APPLY_TO_DIR = "OSUpdApplyToD" const UPDATE_ARCHIVE_DIR = "UpdArchD" const LOCAL_DIR = "/data/local"; +const UPDATES_DIR = "updates/0"; +const FOTA_DIR = "updates/fota"; XPCOMUtils.defineLazyServiceGetter(Services, "env", "@mozilla.org/process/environment;1", @@ -64,10 +66,17 @@ DirectoryProvider.prototype = { persistent.value = true; return file; } - if (prop == XRE_OS_UPDATE_APPLY_TO_DIR || - prop == UPDATE_ARCHIVE_DIR) { - let file = this.getUpdateDir(persistent); - return file; + if (prop == UPDATE_ARCHIVE_DIR) { + // getUpdateDir will set persistent to false since it may toggle between + // /data/local/ and /mnt/sdcard based on free space and/or availability + // of the sdcard. + return this.getUpdateDir(persistent, UPDATES_DIR); + } + if (prop == XRE_OS_UPDATE_APPLY_TO_DIR) { + // getUpdateDir will set persistent to false since it may toggle between + // /data/local/ and /mnt/sdcard based on free space and/or availability + // of the sdcard. + return this.getUpdateDir(persistent, FOTA_DIR); } #endif return null; @@ -92,14 +101,14 @@ DirectoryProvider.prototype = { return requiredSpace <= stat.freeBytes; }, - findUpdateDirWithFreeSpace: function dp_findUpdateDirWithFreeSpace(requiredSpace) { + findUpdateDirWithFreeSpace: function dp_findUpdateDirWithFreeSpace(requiredSpace, subdir) { if (!Services.volumeService) { - return this.createUpdatesDir(LOCAL_DIR); + return this.createUpdatesDir(LOCAL_DIR, subdir); } let activeUpdate = Services.um.activeUpdate; if (gUseSDCard) { if (this.volumeHasFreeSpace(gExtStorage, requiredSpace)) { - let extUpdateDir = this.createUpdatesDir(gExtStorage); + let extUpdateDir = this.createUpdatesDir(gExtStorage, subdir); if (extUpdateDir !== null) { return extUpdateDir; } @@ -109,7 +118,7 @@ DirectoryProvider.prototype = { } if (this.volumeHasFreeSpace(LOCAL_DIR, requiredSpace)) { - let localUpdateDir = this.createUpdatesDir(LOCAL_DIR); + let localUpdateDir = this.createUpdatesDir(LOCAL_DIR, subdir); if (localUpdateDir !== null) { return localUpdateDir; } @@ -120,7 +129,7 @@ DirectoryProvider.prototype = { return null; }, - getUpdateDir: function dp_getUpdateDir(persistent) { + getUpdateDir: function dp_getUpdateDir(persistent, subdir) { let defaultUpdateDir = this.getDefaultUpdateDir(); persistent.value = false; @@ -139,7 +148,7 @@ DirectoryProvider.prototype = { } let requiredSpace = selectedPatch.size * 2; - let updateDir = this.findUpdateDirWithFreeSpace(requiredSpace, persistent); + let updateDir = this.findUpdateDirWithFreeSpace(requiredSpace, subdir); if (updateDir) { return updateDir; } @@ -152,24 +161,25 @@ DirectoryProvider.prototype = { throw Cr.NS_ERROR_FILE_TOO_BIG; }, - createUpdatesDir: function dp_createUpdatesDir(root) { + createUpdatesDir: function dp_createUpdatesDir(root, subdir) { let dir = Cc["@mozilla.org/file/local;1"] .createInstance(Ci.nsILocalFile); dir.initWithPath(root); if (!dir.isWritable()) { + log("Error: " + dir.path + " isn't writable"); return null; } - dir.appendRelativePath("updates/0"); + dir.appendRelativePath(subdir); if (dir.exists()) { if (dir.isDirectory() && dir.isWritable()) { return dir; } - // updates/0 is either a file or isn't writable. In either case we + // subdir is either a file or isn't writable. In either case we // can't use it. log("Error: " + dir.path + " is a file or isn't writable"); return null; } - // updates/0 doesn't exist, and the parent is writable, so try to + // subdir doesn't exist, and the parent is writable, so try to // create it. This can fail if a file named updates exists. try { dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0770); diff --git a/b2g/components/RecoveryService.js b/b2g/components/RecoveryService.js index dda4215d3e36..6b680930dcc9 100644 --- a/b2g/components/RecoveryService.js +++ b/b2g/components/RecoveryService.js @@ -19,7 +19,12 @@ function log(msg) { #ifdef MOZ_WIDGET_GONK let librecovery = (function() { - let library = ctypes.open("librecovery.so"); + try { + let library = ctypes.open("librecovery.so"); + } catch (e) { + log("Unable to open librecovery.so"); + throw Cr.NS_ERROR_FAILURE; + } let FotaUpdateStatus = new ctypes.StructType("FotaUpdateStatus", [ { result: ctypes.int }, { updatePath: ctypes.char.ptr } @@ -73,7 +78,6 @@ RecoveryService.prototype = { log("Error: FOTA install failed"); } #endif - throw Cr.NS_ERROR_FAILURE; }, @@ -81,6 +85,7 @@ RecoveryService.prototype = { let status = Ci.nsIRecoveryService.FOTA_UPDATE_UNKNOWN; #ifdef MOZ_WIDGET_GONK let cStatus = librecovery.FotaUpdateStatus(); + if (librecovery.getFotaUpdateStatus(cStatus.address()) == 0) { status = cStatus.result; } diff --git a/b2g/components/UpdatePrompt.js b/b2g/components/UpdatePrompt.js index 5e5c92b0dfd0..e11f286bdbde 100644 --- a/b2g/components/UpdatePrompt.js +++ b/b2g/components/UpdatePrompt.js @@ -8,6 +8,7 @@ const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; +const Cr = Components.results; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); @@ -374,16 +375,21 @@ UpdatePrompt.prototype = { }, finishOSUpdate: function UP_finishOSUpdate(aOsUpdatePath) { - let recoveryService = Cc["@mozilla.org/recovery-service;1"] - .getService(Ci.nsIRecoveryService); - log("Rebooting into recovery to apply FOTA update: " + aOsUpdatePath); try { + let recoveryService = Cc["@mozilla.org/recovery-service;1"] + .getService(Ci.nsIRecoveryService); recoveryService.installFotaUpdate(aOsUpdatePath); } catch(e) { log("Error: Couldn't reboot into recovery to apply FOTA update " + aOsUpdatePath); + aUpdate = Services.um.activeUpdate; + if (aUpdate) { + aUpdate.errorCode = Cr.NS_ERROR_FAILURE; + aUpdate.statusText = "fota-reboot-failed"; + this.showUpdateError(aUpdate); + } } },