Merge lp:~humpolec-team/humpolec/UbuntuInstaller-ota into lp:humpolec

Proposed by Rex Tsai
Status: Merged
Approved by: Yuan-Chen Cheng
Approved revision: 45
Merge reported by: Rex Tsai
Merged at revision: not available
Proposed branch: lp:~humpolec-team/humpolec/UbuntuInstaller-ota
Merge into: lp:humpolec
Diff against target: 1175 lines (+428/-315)
7 files modified
AndroidManifest.xml (+1/-0)
assets/system-image-upgrader (+16/-11)
assets/upgrade-checker (+16/-0)
src/com/canonical/ubuntu/installer/InstallActivity.java (+34/-32)
src/com/canonical/ubuntu/installer/LaunchActivity.java (+29/-6)
src/com/canonical/ubuntu/installer/UbuntuInstallService.java (+332/-262)
src/com/canonical/ubuntu/installer/VersionInfo.java (+0/-4)
To merge this branch: bzr merge lp:~humpolec-team/humpolec/UbuntuInstaller-ota
Reviewer Review Type Date Requested Status
Yuan-Chen Cheng Approve
Review via email: mp+200035@code.launchpad.net

Description of the change

Support Ubuntu Touch upgrade.

* Find update_command in /cache/recovery, if update_command comes from /cache, it's upgradeable.
* Added Upgradeable checking script, check if upgrade image available in /cache
* Use INSTALLED_VERSION as DOWNLOADED_VERSION for system upgrade, since we don't know what's the version in /cache.
* New Intent Servcie for checking upgrade.
* make doInstallUbuntu works with images file stored in /cache.
* clean up UpdateComamnd function.
* only using executeSUCommands for shell access.

To post a comment you must log in.
Revision history for this message
Yuan-Chen Cheng (ycheng-twn) wrote :

line 35: why not move BUSYBOX=busybox up and
        cd `${BUSYBOX} dirname $1`

line 104: what's "user's data" did you mean ?
        user data that android create, user data that ubuntu user create or ?

line 335: will it better to name something like IS_UBUNTU_UPGRADABLE
        instead of UPGRADE_UBUNTU

line 425: can you add comment on the logic ? like
        As working dir in /data, blalal
        As working dir in /cache, blalal

line 1140: please also add comment like line 425. (or refer to it)

line 1082, "getApplication()." can be removed.

line 1034: UbuntuInstallService.isUpgradeable
        check command file against /cache works in this case, but it
        does not necessary means upgradable (it might means some
        error on internal status keeping) since normal install
        could have command file in /cache if the apk is installed
        in ROM.

        should we rename this function to something else ?

Maybe we should stop adding new code and try to document the state machine.
Maybe more re-factor then.

review: Needs Fixing
40. By Rex Tsai

use for busybox.

41. By Rex Tsai

Removed confusing comment on Ubuntu user data.

42. By Rex Tsai

s/UPGRADE_UBUNTU/IS_UBUNTU_UPGRADABLE/

43. By Rex Tsai

Comment on updates command checking.

44. By Rex Tsai

Add comment on findUpgradeable()

45. By Rex Tsai

s/findUpgradeable/findInstallCommand/

Revision history for this message
Rex Tsai (chihchun) wrote :

Changes for meet YC's requests.

* 2f4e386 - s/findUpgradeable/findInstallCommand/
* 6b5b8b9 - Add comment on findUpgradeable()
* 64ca88b - Comment on updates command checking.
* 686a879 - s/UPGRADE_UBUNTU/IS_UBUNTU_UPGRADABLE/
* 2d031a6 - Removed confusing comment on Ubuntu user data.
* 33e8eea - use ${BUSYBOX} for busybox.

Revision history for this message
Yuan-Chen Cheng (ycheng-twn) wrote :

+1

I still don't like the function name isUpgradeable, but it's too personal and the code is good enough for now.

review: Approve
Revision history for this message
Rex Tsai (chihchun) wrote :

I think we can integrate both checkifReadyToInstall and isUpgradeable into one function.
But need to clean up how we manage Shared Preferences data.

I will do merge first.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'AndroidManifest.xml'
2--- AndroidManifest.xml 2013-12-21 16:59:18 +0000
3+++ AndroidManifest.xml 2013-12-26 07:18:46 +0000
4@@ -62,6 +62,7 @@
5 <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.GET_SERVICE_STATE" />
6 <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.GET_PROGRESS_STATUS" />
7 <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.REBOOT_UBUNTU" />
8+ <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.IS_UBUNTU_UPGRADABLE" />
9 </intent-filter>
10 </service>
11 </application>
12
13=== modified file 'assets/system-image-upgrader'
14--- assets/system-image-upgrader 2013-12-20 03:39:53 +0000
15+++ assets/system-image-upgrader 2013-12-26 07:18:46 +0000
16@@ -1,25 +1,30 @@
17-#!/sbin/sh
18+#!/system/bin/sh
19+# Copyright (C) 2013 Canonical Ltd.
20
21-export PATH=$PATH:${PWD}
22-UPDATE_FOLDER=${PWD}
23-PRIVATE_DIR=$2
24-BUSYBOX=busybox
25-TAR=u_tar
26-set -e
27+# $0 [ubuntu command file] [app/private folder]
28
29 if [ ! -e "$1" ]; then
30 echo "Command file doesn't exist: $1"
31 exit 1
32 fi
33-mv $1 $1.applying
34+
35 COMMAND_FILE=$1.applying
36-
37 REMOVE_LIST="$COMMAND_FILE"
38-
39+UPDATE_FOLDER=${PWD}
40+PRIVATE_DIR=$2
41+BUSYBOX=busybox
42+TAR=u_tar
43 TMP=/cache/tmp
44+export PATH=${PWD}:${PRIVATE_DIR}:$PATH
45
46+set -e
47 echo "Starting image upgrader: $(date)"
48
49+# switch to the update command folder, which has the images
50+cd `$BUSYBOX dirname $1`
51+mv $1 $1.applying
52+
53+
54 # Functions
55 verify_signature() {
56 return 0
57@@ -143,7 +148,7 @@
58
59 # Process the command file
60 FULL_IMAGE=0
61-echo "Processing the command file"
62+echo "Processing the command file $COMMAND_FILE"
63 while read line
64 do
65 set -- $line
66
67=== added file 'assets/upgrade-checker'
68--- assets/upgrade-checker 1970-01-01 00:00:00 +0000
69+++ assets/upgrade-checker 2013-12-26 07:18:46 +0000
70@@ -0,0 +1,16 @@
71+#!/system/bin/sh
72+# Copyright (C) 2013 Canonical Ltd.
73+#
74+# Check if ubuntu_command exist
75+# print the path and exit 0 if found.
76+
77+FILES=$@
78+
79+for file in $FILES ; do
80+ if [[ -f $file ]] ; then
81+ echo $file
82+ exit 1
83+ fi
84+done
85+
86+exit 0
87
88=== modified file 'src/com/canonical/ubuntu/installer/InstallActivity.java'
89--- src/com/canonical/ubuntu/installer/InstallActivity.java 2013-12-25 06:09:49 +0000
90+++ src/com/canonical/ubuntu/installer/InstallActivity.java 2013-12-26 07:18:46 +0000
91@@ -114,14 +114,14 @@
92 }
93 mObserversRegistered = false;
94 }
95-
96+
97 @Override
98 public boolean onCreateOptionsMenu(Menu menu) {
99 // Inflate the menu; this adds items to the action bar if it is present.
100 getMenuInflater().inflate(R.menu.installer_menu, menu);
101 return true;
102 }
103-
104+
105 @Override
106 public boolean onOptionsItemSelected(MenuItem item) {
107 switch (item.getItemId()) {
108@@ -183,11 +183,13 @@
109 }
110
111 private void checkIfUbuntuIsInstalled() {
112- // check is there is Ubuntu installed
113- if (UbuntuInstallService.isUbuntuInstalled(this.getApplicationContext())) {
114- // go to launch screen, and kill this activity.
115- LaunchActivity.startFrom(this);
116- finish();
117+ // check is there is Ubuntu installed or is upgradeable
118+ if (UbuntuInstallService.isUbuntuInstalled(getApplicationContext())) {
119+ if(!UbuntuInstallService.isUpgradeable(getApplicationContext())) {
120+ Log.d(TAG, "go to launch screen, and kill Install activity");
121+ LaunchActivity.startFrom(this);
122+ finish();
123+ }
124 }
125 }
126
127@@ -262,7 +264,7 @@
128 // reset progress bar
129 mProgressBar.setProgress(0);
130 }
131-
132+
133 TextPickerDialog.OnChannelPicktListener mInstallDialogListener
134 = new TextPickerDialog.OnChannelPicktListener() {
135 public void onChannelPicked(Context context, String channel, boolean bootstrap, boolean latest) {
136@@ -292,38 +294,38 @@
137
138 private void downloadVersion(final Context context, final String channel, final boolean bootstrap) {
139 final ProgressDialog progress = ProgressDialog.show(this,
140- "Fetching versions",
141- "Checking list of availanble versions for choosen channel", true);
142+ "Fetching versions",
143+ "Checking list of availanble versions for choosen channel", true);
144 new Thread(new Runnable() {
145 @Override
146 public void run() {
147 String jsonStr = Utils.httpDownload(UbuntuInstallService.BASE_URL
148- + mAvailableChannels.get(channel));
149+ + mAvailableChannels.get(channel));
150 // TODO: handle malformed JSON
151 final List<Image> releases = JsonChannelParser.getAvailableReleases(jsonStr, ReleaseType.FULL);
152-
153+
154 runOnUiThread(new Runnable() {
155- @Override
156+ @Override
157 public void run() {
158 progress.dismiss();
159 // if there are available releases, show number picker
160 if (releases.size() != 0 && releases.get(0).files.length != 0) {
161- int[] values = new int[releases.size()];
162- for (int i = 0 ; i < values.length ; ++i) {
163- values[i] = releases.get(i).version;
164- }
165- new NumberPickerDialog(context,
166- R.string.version_picker_dialog_title,
167- R.string.action_install,
168- R.string.cancel,
169- values,
170- 0,
171- new NumberPickerDialog.OnNumberPicktListener() {
172- @Override
173- public void onNumberSelected(Context context, int value) {
174- startDownload(channel, bootstrap, value);
175- }
176- }).show();;
177+ int[] values = new int[releases.size()];
178+ for (int i = 0 ; i < values.length ; ++i) {
179+ values[i] = releases.get(i).version;
180+ }
181+ new NumberPickerDialog(context,
182+ R.string.version_picker_dialog_title,
183+ R.string.action_install,
184+ R.string.cancel,
185+ values,
186+ 0,
187+ new NumberPickerDialog.OnNumberPicktListener() {
188+ @Override
189+ public void onNumberSelected(Context context, int value) {
190+ startDownload(channel, bootstrap, value);
191+ }
192+ }).show();;
193 }
194 }
195 });
196@@ -359,7 +361,7 @@
197 mProgressText.setText("");
198 }
199 }
200- break;
201+ break;
202 case FETCHING_CHANNELS:
203 mInstallButton.setText(Html.fromHtml(getResources().getString(R.string.install_button_label_fetching)));
204 mInstallButton.setEnabled(false);
205@@ -406,7 +408,7 @@
206 int progress = intent.getIntExtra(UbuntuInstallService.PROGRESS_EXTRA_INT, -1);
207 if (progress != -1) {
208 mProgressBar.setProgress(progress);
209- Log.v(TAG, "Progress:" + progress);
210+ Log.d(TAG, "Progress: " + progress);
211 }
212 if (p != null && !p.equals("")) {
213 // update terminal with progress text
214@@ -440,7 +442,7 @@
215 }
216 updateUiElements();
217 }
218-
219+
220 // Handle download result
221 } else if(action.equals(UbuntuInstallService.DOWNLOAD_RESULT)) {
222 int r = intent.getIntExtra(UbuntuInstallService.DOWNLOAD_RESULT_EXTRA_INT, -1);
223
224=== modified file 'src/com/canonical/ubuntu/installer/LaunchActivity.java'
225--- src/com/canonical/ubuntu/installer/LaunchActivity.java 2013-12-19 09:36:28 +0000
226+++ src/com/canonical/ubuntu/installer/LaunchActivity.java 2013-12-26 07:18:46 +0000
227@@ -8,6 +8,7 @@
228 import android.content.Intent;
229 import android.content.IntentFilter;
230 import android.os.Bundle;
231+import android.util.Log;
232 import android.view.Menu;
233 import android.view.MenuItem;
234 import android.view.View;
235@@ -16,7 +17,6 @@
236
237 import com.canonical.ubuntu.widget.UbuntuButton;
238
239-
240 public class LaunchActivity extends Activity {
241 private static final String TAG = "UbuntuLaunchActivity";
242 private UbuntuButton mRebootButton;
243@@ -28,7 +28,7 @@
244 private TextView mTextDescriptionLabel;
245 private TextView mTextDescription;
246 private VersionInfo mUbuntuVersion;
247-
248+
249 @Override
250 protected void onCreate(Bundle savedInstanceState) {
251 super.onCreate(savedInstanceState);
252@@ -48,8 +48,11 @@
253 mTextTitle.setText(R.string.launch_title);
254 mRebootButton.setText(R.string.reboot_button_label);
255 fillInstalledVersionInfo();
256+
257+ // check the upgradeable image.
258+ startService(new Intent(UbuntuInstallService.IS_UBUNTU_UPGRADABLE));
259 }
260-
261+
262 @Override
263 public void onResume() {
264 super.onResume();
265@@ -62,7 +65,7 @@
266 filter.addAction(UbuntuInstallService.VERSION_UPDATE);
267 registerReceiver(mServiceObserver, filter);
268 }
269-
270+
271 @Override
272 public void onPause() {
273 super.onPause();
274@@ -113,7 +116,19 @@
275 }
276 return super.onOptionsItemSelected(item);
277 }
278-
279+
280+ /**
281+ * Create a dialog for confirmation.
282+ * @param title
283+ * @param positiveButton
284+ * @param negativeButton
285+ * @param action
286+ * @param toastText
287+ * @param choiceItemsArray
288+ * @param defaultChoiceValues
289+ * @param choiceClickListener
290+ * @return AlertDialog
291+ */
292 private AlertDialog createConfirmationDialog(final int title,
293 final int positiveButton,
294 final int negativeButton,
295@@ -151,7 +166,10 @@
296 mTextVersionLabel.setText(R.string.label_version);
297 mTextDescriptionLabel.setText(R.string.label_description);
298 }
299-
300+
301+ /**
302+ * Get installed version to check Ubuntu is installed
303+ */
304 private void ensureUbuntuIsInstalled() {
305 VersionInfo v = UbuntuInstallService.getInstalledVersion(this.getApplicationContext());
306 if (v == null) {
307@@ -177,6 +195,11 @@
308 String action = intent.getAction();
309 if (action.equals(UbuntuInstallService.VERSION_UPDATE)) {
310 ensureUbuntuIsInstalled();
311+ if(UbuntuInstallService.isUpgradeable(getApplicationContext())) {
312+ Log.d(TAG, "Found upgradeable file, kill LaunchActivity");
313+ InstallActivity.startFrom(context);
314+ finish();
315+ }
316 }
317 }
318 };
319
320=== modified file 'src/com/canonical/ubuntu/installer/UbuntuInstallService.java'
321--- src/com/canonical/ubuntu/installer/UbuntuInstallService.java 2013-12-24 09:14:25 +0000
322+++ src/com/canonical/ubuntu/installer/UbuntuInstallService.java 2013-12-26 07:18:46 +0000
323@@ -9,6 +9,7 @@
324 import java.net.MalformedURLException;
325 import java.net.URL;
326 import java.net.URLConnection;
327+import java.util.ArrayList;
328 import java.util.Collections;
329 import java.util.HashMap;
330 import java.util.Iterator;
331@@ -90,6 +91,7 @@
332 public static final String INSTALL_UBUNTU = "com.canonical.ubuntuinstaller.UbuntuInstallService.INSTALL_UBUNTU";
333 public static final String CANCEL_INSTALL = "com.canonical.ubuntuinstaller.UbuntuInstallService.CANCEL_INSTALL";
334 public static final String UNINSTALL_UBUNTU = "com.canonical.ubuntuinstaller.UbuntuInstallService.UINSTALL_UBUNTU";
335+ public static final String IS_UBUNTU_UPGRADABLE = "com.canonical.ubuntuinstaller.UbuntuInstallService.IS_UBUNTU_UPGRADABLE";
336 public static final String UNINSTALL_UBUNTU_EXTRA_REMOVE_USER_DATA = "user_data";
337 public static final String CHECK_FOR_UPDATE = "com.canonical.ubuntuinstaller.UbuntuInstallService.CHECK_FOR_UPDATE";
338 public static final String DELETE_UBUNTU_USER_DATA = "com.canonical.ubuntuinstaller.UbuntuInstallService.DELETE_USER_DATA";
339@@ -151,6 +153,7 @@
340 private static final String TAR = "u_tar";
341 private static final String ANDROID_LOOP_MOUNT = "aloopmount";
342 private static final String ANDROID_BOOTMGR = "bootmgr";
343+ private static final String UPGRADECHECKER = "upgrade-checker";
344 private static final String UPDATE_SCRIPT = "system-image-upgrader";
345 private static final String ARCHIVE_MASTER = "archive-master.tar.xz";
346 private static final String ARCHIVE_MASTER_ASC = "archive-master.tar.xz.asc";
347@@ -179,6 +182,7 @@
348 private static final int PROGRESS_MKSWAP_ADJUSTMENT = 17; // equivalent of time tar --checkpoint=200
349 private PowerManager mPowerManager;
350 private PowerManager.WakeLock mWakeLock;
351+ // FIXME make workPath in Cache a private function
352 private boolean workPathInCache = false;
353 private String mRootOfWorkPath;
354 private boolean mIsCanceled;
355@@ -210,7 +214,16 @@
356 }
357
358 public ESumNotMatchException(String string) {
359- // TODO Auto-generated constructor stub
360+ super(string);
361+ }
362+ };
363+
364+ class EShellExecException extends Exception {
365+ public EShellExecException(){
366+ super();
367+ }
368+
369+ public EShellExecException(String string) {
370 super(string);
371 }
372 };
373@@ -218,7 +231,7 @@
374 public UbuntuInstallService() {
375 super(TAG);
376 }
377-
378+
379 @Override
380 public void onCreate() {
381 super.onCreate();
382@@ -231,7 +244,7 @@
383 mRootOfWorkPath = "/cache";
384 workPathInCache = true;
385 } else {
386- mRootOfWorkPath = getFilesDir().toString(); // "/data/data/com.canonical.ubuntuinstaller/files";
387+ mRootOfWorkPath = getFilesDir().toString(); // "/data/data/com.canonical.ubuntu.installer/files";
388 workPathInCache = false;
389 }
390 mInstallerState = InstallerState.READY;
391@@ -281,6 +294,12 @@
392 } else if (action.equals(INSTALL_UBUNTU)) {
393 updateInstallerState(InstallerState.INSTALLING);
394 result = doInstallUbuntu(intent);
395+ } else if (action.equals(IS_UBUNTU_UPGRADABLE)) {
396+ // check if the upgradeable images available.
397+ if(findInstallCommand()) {
398+ Log.d(TAG, "There is a upgradeable file. send VERSION_UPDATE");
399+ result = new Intent(VERSION_UPDATE);
400+ }
401 } else if (action.equals(CANCEL_INSTALL)) {
402 // install should be already cancelled, try to delete it now
403 updateInstallerState(InstallerState.UNINSTALLING);
404@@ -309,7 +328,7 @@
405
406 private Intent doGetChannelList(Intent intent) {
407 Intent result = new Intent(AVAILABLE_CHANNELS);
408- //
409+
410 HashMap<String, String> channels= new HashMap<String, String>();
411 boolean includeHidden = getSharedPreferences( SHARED_PREF, Context.MODE_PRIVATE).getBoolean(PREF_KEY_DEVELOPER, false);
412 String deviceModel = Build.DEVICE.toLowerCase(Locale.US);
413@@ -365,149 +384,74 @@
414 }
415
416 private Intent doInstallUbuntu(Intent intent) {
417- Log.w(TAG, "doInstallUbuntu");
418+ Log.w(TAG, "doInstallUbuntu");
419 Intent result = new Intent(INSTALL_RESULT);
420+
421 // get update command file
422- SharedPreferences pref = getSharedPreferences( SHARED_PREF, Context.MODE_PRIVATE);
423- String updateCommand = pref.getString(PREF_KEY_UPDATE_COMMAND,"");
424+ String updateCommand = getUpdateCommand();
425+
426+ // 1. check if update command exist.
427+ // 2. However, if the udpate command is in "/cache",
428+ // the app can not access to /cache sometimes.
429+ if (updateCommand.equals("") ||
430+ (!new File(updateCommand).exists() &&
431+ !updateCommand.startsWith("/cache"))) {
432+ return handleInstallFail(result, -1, "Missing update command");
433+ }
434+
435+ SharedPreferences pref = getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE);
436 mTotalSize = pref.getInt(PREF_KEY_ESTIMATED_CHECKPOINTS, 0);
437 mLastSignalledProgress = 0;
438- if (updateCommand.equals("") || ! new File(updateCommand).exists()) {
439- return handleInstallFail(result, -1, "Missing update command");
440- }
441- mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ubuntu-installing");
442- try {
443- File rootFolder = new File(mRootOfWorkPath);
444- File supportingFiles = new File(rootFolder, RELEASE_FOLDER);
445- broadcastProgress(0, "Extracting supporting files");
446- try {
447- Utils.extractExecutableAsset(this, BUSYBOX, supportingFiles.toString(), true);
448- Utils.extractExecutableAsset(this, ANDROID_BOOTMGR, supportingFiles.toString(), true);
449- Utils.extractExecutableAsset(this, GPG, supportingFiles.toString(), true);
450- Utils.extractExecutableAsset(this, TAR, supportingFiles.toString(), true);
451- Utils.extractExecutableAsset(this, UPDATE_SCRIPT, supportingFiles.toString(), true);
452- Utils.extractExecutableAsset(this, ANDROID_LOOP_MOUNT, supportingFiles.toString(), true);
453- Utils.extractExecutableAsset(this, ARCHIVE_MASTER, supportingFiles.toString(), false);
454- Utils.extractExecutableAsset(this, ARCHIVE_MASTER_ASC, supportingFiles.toString(), false);
455- Utils.extractExecutableAsset(this, U_REBOOT_APP, supportingFiles.toString(), false);
456- Utils.extractExecutableAsset(this, U_REBOOT_APP_ASC, supportingFiles.toString(), false);
457- } catch (IOException e) {
458- e.printStackTrace();
459- return handleInstallFail(result, -1, "Failed to extract supporting assets");
460- }
461- // get superuser and run update script
462- broadcastProgress(-1, "Starting update script");
463- try {
464- Process process = Runtime.getRuntime().exec("su", null, supportingFiles);
465- DataOutputStream os = new DataOutputStream(process.getOutputStream());
466- // debug purpose.
467- // os.writeBytes("set -x\n");
468- // make sure we are in work folder
469- os.writeBytes(String.format("cd %s\n", supportingFiles.getAbsolutePath()));
470- os.writeBytes("echo \"SU granted\"\n");
471- // run system-image-upgrader.
472- os.writeBytes(String.format("sh %s %s %s\n",
473- UPDATE_SCRIPT,
474- updateCommand,
475- getFilesDir().getAbsolutePath()
476- ));
477- os.writeBytes(String.format("cd %s\n", supportingFiles.getAbsolutePath()));
478- // backup original recovery.
479- if(!new File(getFilesDir().toString(), ANDROID_REOCVERY_IMG).exists()) {
480- os.writeBytes(String.format("./%s -b %s %s/%s\n",
481- ANDROID_BOOTMGR,
482- Utils.getRecoveryPartitionPath(),
483- getFilesDir().getAbsolutePath(),
484- ANDROID_REOCVERY_IMG
485- ));
486- }
487- os.writeBytes(String.format("cd %s\n", supportingFiles.getAbsolutePath()));
488- // overwrite the recovery partition.
489- os.writeBytes(String.format("./%s -b %s/%s %s\n",
490+
491+ List<String> shellcmds = new ArrayList<String>();
492+ {
493+ shellcmds.add("echo Installing\n");
494+ // run system-image-upgrader.
495+ shellcmds.add(String.format("%s %s %s\n",
496+ UPDATE_SCRIPT,
497+ updateCommand,
498+ getFilesDir().getAbsolutePath()
499+ ));
500+ // Only backup original recovery, when there is no backuped file.
501+ if(!new File(getFilesDir().toString(), ANDROID_REOCVERY_IMG).exists()) {
502+ shellcmds.add(String.format("%s -b %s %s/%s\n",
503 ANDROID_BOOTMGR,
504+ Utils.getRecoveryPartitionPath(),
505 getFilesDir().getAbsolutePath(),
506- UBUNTU_BOOT_IMG,
507- Utils.getRecoveryPartitionPath()
508+ ANDROID_REOCVERY_IMG
509 ));
510-
511- // close terminal
512- os.writeBytes("exit\n");
513- os.flush();
514- InputStream is = process.getInputStream();
515- InputStream es = process.getErrorStream();
516- int read = 0;
517- byte[] buff = new byte[4096];
518- boolean running = true;
519- boolean scriptExecuted = false;
520- do {
521- while( is.available() > 0) {
522- read = is.read(buff);
523- if ( read <= 0 ) {
524- break;
525- }
526- scriptExecuted = true;
527- String seg = new String(buff,0,read);
528- Log.d(TAG, "Script Output: " + seg);
529- broadcastProgress(-1, seg);
530- }
531- while( es.available() > 0) {
532- read = es.read(buff);
533- if ( read <= 0 ) {
534- break;
535- }
536- scriptExecuted = true;
537- String seg = new String(buff,0,read);
538- if (seg.startsWith("SWAP-file-missing")) {
539- // this is signal that we will also install swap, adjust progress estimates
540- mTotalSize += PROGRESS_MKSWAP_ADJUSTMENT + PROGRESS_SWAP_CREATION_ADJUSTMENT;
541- } else {
542- mProgress++;
543- if ( mLastSignalledProgress < (mProgress * 100 / mTotalSize)) {
544- // update and signal new progress
545- mLastSignalledProgress = (int) (mProgress * 100 / mTotalSize);
546- broadcastProgress(mLastSignalledProgress, null);
547- }
548- }
549- Log.d(TAG, "Stderr Output: " + seg);
550- }
551- try {
552- int ret = process.exitValue();
553- Log.v(TAG, "Worker thread exited with: " + ret);
554- // if script was not executed, then user did not granted SU permissions
555- if (ret == 255 || !scriptExecuted ) {
556- return handleInstallFail(result, -1, "Failed to get SU permissions");
557- } else if (ret != 0) {
558- return handleInstallFail(result, -1, "Instalation failed");
559- }
560- running =false;
561- } catch (IllegalThreadStateException e) {
562- // still running, wait a bit
563- try { Thread.sleep(200); } catch(Exception ex) {}
564- }
565- } while (running);
566- } catch (IOException e) {
567- e.printStackTrace();
568- Log.w(TAG, "Update failed");
569- return handleInstallFail(result, -1, "Install failed");
570- }
571- } finally {
572- if (mWakeLock != null && mWakeLock.isHeld()) {
573- mWakeLock.release();
574- }
575- }
576- SharedPreferences.Editor editor = pref.edit();
577- editor.putString(PREF_KEY_UPDATE_COMMAND, "");
578+ }
579+ // overwrite the recovery partition.
580+ shellcmds.add(String.format("%s -b %s/%s %s\n",
581+ ANDROID_BOOTMGR,
582+ getFilesDir().getAbsolutePath(),
583+ UBUNTU_BOOT_IMG,
584+ Utils.getRecoveryPartitionPath()
585+ ));
586+ shellcmds.add("exit");
587+ }
588+
589+ broadcastProgress(-1, "Starting update script - " + updateCommand);
590+ try {
591+ int ret = executeSUCommands(shellcmds.toArray(new String[shellcmds.size()]));
592+ result.putExtra(INSTALL_RESULT_EXTRA_INT, ret);
593+ } catch (EShellExecException e) {
594+ return handleInstallFail(result, -1, e.getMessage());
595+ }
596+
597+ // we done.
598+ cleanUpdateCommand();
599 VersionInfo v = new VersionInfo(pref, PREF_KEY_DOWNLOADED_VERSION);
600- v.storeVersion(editor, PREF_KEY_INSTALLED_VERSION);
601+ v.storeVersion(pref.edit(), PREF_KEY_INSTALLED_VERSION);
602 mProgress = 100;
603- result.putExtra(INSTALL_RESULT_EXTRA_INT, 0);
604 return result;
605 }
606-
607+
608 private Intent handleInstallFail(Intent i, int res, String failReason) {
609 i.putExtra(INSTALL_RESULT_EXTRA_INT, -1);
610- i.putExtra(INSTALL_RESULT_EXTRA_STR, "Missing update command");
611- doUninstallUbuntu(i);
612+ i.putExtra(INSTALL_RESULT_EXTRA_STR, failReason);
613+ // we don't want to unstainll if we failed to install a update.
614+ // doUninstallUbuntu(i);
615 return i;
616 }
617
618@@ -516,9 +460,11 @@
619 File updateCommand = new File(workingFolder, UPDATE_COMMAND);
620 Intent result = new Intent(VERSION_UPDATE);
621 boolean removeUserData = intent.getBooleanExtra(UNINSTALL_UBUNTU_EXTRA_REMOVE_USER_DATA, false);
622+ Log.d(TAG, "doUninstallUbuntu");
623
624 String format_cmd = null;
625 if (removeUserData) {
626+ Log.d(TAG, "removing user data.");
627 format_cmd = String.format("echo \"%s %s\n %s %s\" > %s\n",
628 COMMAND_FORMAT, PARTITION_DATA,
629 COMMAND_UMOUNT, PARTITION_SYSTEM,
630@@ -532,41 +478,53 @@
631 // 1. force unmount
632 // 2. restore android recovery partition, and deleted it.
633 // 3. delete system.img and SWAP.img.
634- int r = executeSUCommands(result, "result", new String[]{
635- format_cmd,
636- ("sh " + UPDATE_SCRIPT
637- + " " + updateCommand.getAbsolutePath()
638- + " " + getFilesDir().toString() + "\n"),
639- String.format("./%s -b %s/%s %s\n",
640- ANDROID_BOOTMGR,
641- getFilesDir().toString(),
642- ANDROID_REOCVERY_IMG,
643- Utils.getRecoveryPartitionPath()),
644- (String.format("rm -f %s/%s\n", getFilesDir().toString(), ANDROID_REOCVERY_IMG)),
645- ("rm -rf /data/system.img\n"),
646- ("rm -rf /data/SWAP.img\n"),
647- } );
648- if (r == 0) {
649- // delete installed version in preferences
650- SharedPreferences pref = getSharedPreferences( SHARED_PREF, Context.MODE_PRIVATE);
651- SharedPreferences.Editor editor = pref.edit();
652- editor.putString(PREF_KEY_UPDATE_COMMAND, "");
653- VersionInfo.storeEmptyVersion(editor, PREF_KEY_INSTALLED_VERSION);
654- editor.commit();
655+ try {
656+ int r = executeSUCommands(
657+ new String[]{
658+ ("echo Uninstalling\n"),
659+ format_cmd,
660+ ("sh " + UPDATE_SCRIPT
661+ + " " + updateCommand.getAbsolutePath()
662+ + " " + getFilesDir().toString() + "\n"),
663+ String.format("%s -b %s/%s %s || true\n",
664+ ANDROID_BOOTMGR,
665+ getFilesDir().toString(),
666+ ANDROID_REOCVERY_IMG,
667+ Utils.getRecoveryPartitionPath()),
668+ (String.format("rm -f %s/%s || true\n", getFilesDir().toString(), ANDROID_REOCVERY_IMG)),
669+ ("rm -rf /data/system.img || true\n"),
670+ ("rm -rf /data/SWAP.img || true\n"),
671+ } );
672+
673+ if (r == 0) {
674+ // delete installed version in preferences
675+ cleanUpdateCommand();
676+ VersionInfo.storeEmptyVersion(
677+ getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE).edit(), PREF_KEY_INSTALLED_VERSION);
678+ }
679+ result.putExtra("result", r);
680+ } catch (EShellExecException e) {
681+ result.putExtra("result", -1);
682 }
683- result.putExtra("result", r);
684+
685 return result;
686 }
687
688 private Intent doDeleteUbuntuUserData(Intent intent) {
689 Intent result = new Intent(VERSION_UPDATE);
690 File workingFolder = new File(mRootOfWorkPath, TEMP_FOLDER);
691- File updateCommand = new File(workingFolder, UPDATE_COMMAND);
692- int r = executeSUCommands(result, "fail_description", new String[]{
693+ File updateCommand = new File(workingFolder, UPDATE_COMMAND);
694+
695+ try {
696+ int r = executeSUCommands(new String[]{
697 String.format("echo \"%s %s\" > %s\n", COMMAND_FORMAT, PARTITION_DATA, UPDATE_COMMAND),
698 ("sh " + UPDATE_SCRIPT + " " + updateCommand.getAbsolutePath() + " " + getFilesDir().toString() + "\n")
699- } );
700- result.putExtra("result", r);
701+ } );
702+ result.putExtra("result", r);
703+ } catch (EShellExecException e) {
704+ result.putExtra("fail_description", e.getMessage());
705+ result.putExtra("result", -1);
706+ }
707 return result;
708 }
709
710@@ -579,75 +537,83 @@
711 // FIXME: in Android 4.4, we do not get power manager permission.
712 // try it with SU permissions
713 try {
714- Process process = Runtime.getRuntime().exec("su", null, getFilesDir());
715- DataOutputStream os = new DataOutputStream(process.getOutputStream());
716-
717- Utils.extractExecutableAsset(this, ANDROID_BOOTMGR, getFilesDir().toString(), true);
718- // overwrite the recovery partition.
719- os.writeBytes(String.format("%s/%s -b %s/%s %s\n",
720- getFilesDir().getAbsolutePath(),
721- ANDROID_BOOTMGR,
722- getFilesDir().getAbsolutePath(),
723- UBUNTU_BOOT_IMG,
724- Utils.getRecoveryPartitionPath()
725- ));
726- os.writeBytes("reboot recovery\n");
727- os.flush();
728- try {
729- process.waitFor();
730- if (process.exitValue() != 255) {
731- Utils.showToast(this.getApplicationContext(), "Rebooting to Ubuntu");
732- } else {
733- Utils.showToast(this.getApplicationContext(), "No permissions to reboot to recovery");
734- }
735- } catch (InterruptedException ee) {
736- Utils.showToast(this.getApplicationContext(), "No permissions to reboot to recovery");
737+ int r = executeSUCommands(new String[] {
738+ String.format("%s -b %s/%s %s || true\n",
739+ ANDROID_BOOTMGR,
740+ getFilesDir().getAbsolutePath(),
741+ UBUNTU_BOOT_IMG,
742+ Utils.getRecoveryPartitionPath()),
743+ "reboot recovery\n"
744+ });
745+ if(r != 255) {
746+ Utils.showToast(this.getApplicationContext(), "Rebooting to Ubuntu");
747+ } else {
748+ Utils.showToast(this.getApplicationContext(), "No permissions to reboot to recovery");
749 }
750- } catch (IOException eee) {
751- Utils.showToast(this.getApplicationContext(), "No permissions to reboot to recovery");
752+ } catch (EShellExecException e1) {
753+ Utils.showToast(this.getApplicationContext(), "No permissions to reboot to recovery");
754 }
755 }
756 }
757
758 /**
759- *
760- * @param result intent to update with result text
761- * @param resultExtraText
762- * @param commands commands to execute
763- * @return 0 for success and -1 for fail
764+ * This command exec commands in the working folder with supporting utils.
765+ *
766+ * @param commands commands to be executed
767+ * @return shell script exit value.
768+ * @throws EShellExecException
769 */
770- private int executeSUCommands(Intent result, String resultExtraText, String[] commands) {
771+ private int executeSUCommands(String[] commands) throws EShellExecException {
772+ int ret = 0;
773 File rootFolder = new File(mRootOfWorkPath);
774 File workingFolder = new File(rootFolder, TEMP_FOLDER);
775+ String workingFolderPath = workingFolder.getAbsolutePath();
776+
777 if (!workingFolder.exists() && !workingFolder.mkdir()) {
778- result.putExtra(resultExtraText, "Failed to create working folder");
779- return -1;
780+ throw(new EShellExecException("Failed to create working folder"));
781 }
782+
783+ broadcastProgress(0, "Extracting supporting files at " + workingFolder.getAbsolutePath());
784 try {
785- Utils.extractExecutableAsset(this, UPDATE_SCRIPT, workingFolder.toString(), true);
786- Utils.extractExecutableAsset(this, ANDROID_LOOP_MOUNT, workingFolder.toString(), true);
787- Utils.extractExecutableAsset(this, ANDROID_BOOTMGR, workingFolder.toString(), true);
788+ // extract utils into working folder.
789+ Utils.extractExecutableAsset(this, ANDROID_BOOTMGR, workingFolderPath, true);
790+ Utils.extractExecutableAsset(this, ANDROID_LOOP_MOUNT, workingFolderPath, true);
791+ Utils.extractExecutableAsset(this, ARCHIVE_MASTER_ASC, workingFolderPath, false);
792+ Utils.extractExecutableAsset(this, ARCHIVE_MASTER, workingFolderPath, false);
793+ Utils.extractExecutableAsset(this, BUSYBOX, workingFolderPath, true);
794+ Utils.extractExecutableAsset(this, GPG, workingFolderPath, true);
795+ Utils.extractExecutableAsset(this, TAR, workingFolderPath, true);
796+ Utils.extractExecutableAsset(this, UPDATE_SCRIPT, workingFolderPath, true);
797+ Utils.extractExecutableAsset(this, U_REBOOT_APP_ASC, workingFolderPath, false);
798+ Utils.extractExecutableAsset(this, U_REBOOT_APP, workingFolderPath, false);
799+ Utils.extractExecutableAsset(this, UPGRADECHECKER, workingFolderPath, true);
800 } catch (IOException e) {
801- e.printStackTrace();
802- result.putExtra(resultExtraText, "Failed to extract supporting files");
803- return -1;
804+ throw(new EShellExecException("Failed to extract supporting utils"));
805 }
806
807- mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ubuntu-installing");
808+ mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "shelling");
809 try {
810 Process process = Runtime.getRuntime().exec("su", null, workingFolder);
811 DataOutputStream os = new DataOutputStream(process.getOutputStream());
812+ // debug purpose.
813+ os.writeBytes("set -x\n");
814+
815+ os.writeBytes("echo \"SU granted\"\n");
816 // make sure we are in work folder
817- os.writeBytes("echo \"SU granted\"\n");
818- for (String c : commands) {
819- Log.v(TAG, "Executing:" + c);
820- // make sure we are always at working folder before running next command
821- os.writeBytes(String.format("cd %s\n", workingFolder.getAbsolutePath()));
822- os.writeBytes(c);
823+ os.writeBytes(String.format("cd %s\n", workingFolder.getAbsolutePath()));
824+ // setup search path for commands
825+ os.writeBytes(String.format("export PATH=%s:$PATH\n", workingFolder.getAbsolutePath()));
826+
827+ for (String cmd : commands) {
828+ Log.d(TAG, "Executing: " + cmd + "\n");
829+ os.writeBytes(cmd + "\n");
830+ os.writeBytes("CMDSTATES=$?\n");
831 }
832+ // clean up supporting utils.
833 os.writeBytes(String.format("rm -rf %s\n", workingFolder.getAbsolutePath()));
834- os.writeBytes("exit\n");
835+ os.writeBytes("exit $CMDSTATES\n");
836 os.flush();
837+
838 int read = 0;
839 byte[] buff = new byte[4096];
840 InputStream is = process.getInputStream();
841@@ -661,7 +627,7 @@
842 break;
843 }
844 scriptExecuted = true;
845- String seg = new String(buff,0,read);
846+ String seg = new String(buff, 0, read);
847 Log.i(TAG, "Script Output: " + seg);
848 broadcastProgress(-1, seg);
849 }
850@@ -672,37 +638,44 @@
851 }
852 scriptExecuted = true;
853 String seg = new String(buff,0,read);
854+
855+ if (seg.startsWith("SWAP-file-missing")) {
856+ // this is signal that we will also install swap, adjust progress estimates
857+ mTotalSize += PROGRESS_MKSWAP_ADJUSTMENT + PROGRESS_SWAP_CREATION_ADJUSTMENT;
858+ } else {
859+ mProgress++;
860+ if (mTotalSize > 0 && mLastSignalledProgress < (mProgress * 100 / mTotalSize)) {
861+ // update and signal new progress
862+ mLastSignalledProgress = (int) (mProgress * 100 / mTotalSize);
863+ broadcastProgress(mLastSignalledProgress, null);
864+ }
865+ }
866+
867 Log.i(TAG, "Stderr Output: " + seg);
868 }
869 try {
870- int ret = process.exitValue();
871- Log.v(TAG, "Worker thread exited with: " + ret);
872+ ret = process.exitValue();
873+ Log.d(TAG, "Worker thread exited with: " + ret);
874 // if script was not executed, then user did not granted SU permissions
875- if (ret == 255 || !scriptExecuted ) {
876- result.putExtra(resultExtraText, "Failed to get SU permissions");
877- return -1;
878- } else if (ret != 0) {
879- result.putExtra(resultExtraText, "Script failed");
880- return -1;
881+ if (!scriptExecuted) {
882+ throw new EShellExecException("Failed to get SU permissions");
883 }
884- running =false;
885+ running = false;
886 } catch (IllegalThreadStateException e) {
887 // still running, wait a bit
888 try { Thread.sleep(200); } catch(Exception ex) {}
889 }
890 } while (running);
891- }catch (IOException e) {
892- e.printStackTrace();
893- result.putExtra(resultExtraText, "Script execution exception");
894- return -1;
895+ } catch (IOException e) {
896+ throw(new EShellExecException("Script execution exception " + e.getMessage()));
897 } finally {
898 if (mWakeLock != null && mWakeLock.isHeld()) {
899 mWakeLock.release();
900 }
901 }
902- return 0;
903+ return ret;
904 }
905-
906+
907 private Intent doDownloadRelease(Intent intent) {
908 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ufa-downloading");
909 mIsCanceled = false;
910@@ -780,7 +753,7 @@
911 }
912
913 // make sure release folder exists
914- File release = new File(rootFolder,RELEASE_FOLDER);
915+ File release = new File(rootFolder, RELEASE_FOLDER);
916 release.mkdir();
917 // download release
918 long time = System.currentTimeMillis();
919@@ -970,8 +943,11 @@
920 }
921 }
922 // store update command
923+ setUpdateCommand(updateCommand.getAbsolutePath());
924+
925+ // updated downloaded information.
926 VersionInfo v = new VersionInfo(alias, jsonUrl, choosenRelease.description, choosenRelease.version, 0, releaseType);
927- editor.putString(PREF_KEY_UPDATE_COMMAND, updateCommand.getAbsolutePath());
928+
929 editor.putInt(PREF_KEY_ESTIMATED_CHECKPOINTS, estimatedCheckCount);
930 v.storeVersion(editor, PREF_KEY_DOWNLOADED_VERSION);
931 mProgress = 100;
932@@ -1071,40 +1047,38 @@
933 return fileName;
934 }
935
936+
937+ private static boolean deleteDirectory(File path) {
938+ if( path.exists() ) {
939+ File[] files = path.listFiles();
940+ for(int i=0; i<files.length; i++) {
941+ if(files[i].isDirectory()) {
942+ deleteDirectory(files[i]);
943+ } else {
944+ files[i].delete();
945+ }
946+ }
947+ }
948+ return( path.delete() );
949+ }
950+
951 /**
952- *
953 * @return null if success or error
954 */
955 private String deleteRelease() {
956 // First delete old release if it exists
957 File rootFolder = new File(mRootOfWorkPath);
958- File release = new File(rootFolder,RELEASE_FOLDER);
959+ File release = new File(rootFolder, RELEASE_FOLDER);
960 if (release.exists()) {
961- try {
962- String command = "rm -rf " + release.getAbsolutePath();
963- Process p = Runtime.getRuntime().exec(command , null, rootFolder);
964- try {
965- p.waitFor();
966- int r = p.exitValue();
967- if (r == 255) {
968- return "failed to remove old download";
969- }
970- } catch (InterruptedException e) {
971- }
972- }catch (IOException e) {
973- e.printStackTrace();
974- Log.w(TAG, "failed to remove old download");
975- return "failed to remove old download";
976- }
977- SharedPreferences pref = getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE);
978- SharedPreferences.Editor editor = pref.edit();
979- editor.putString(PREF_KEY_UPDATE_COMMAND, "");
980- VersionInfo.storeEmptyVersion(editor, PREF_KEY_DOWNLOADED_VERSION);
981- editor.commit();
982+ deleteDirectory(release);
983+ // cleanup update command
984+ cleanUpdateCommand();
985+ // clean up version number.
986+ VersionInfo.storeEmptyVersion(getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE).edit(), PREF_KEY_DOWNLOADED_VERSION);
987 }
988 return null;
989 }
990-
991+
992 private void broadcastInstallerState() {
993 Intent i = new Intent(SERVICE_STATE);
994 i.putExtra(SERVICE_STATE, mInstallerState.ordinal());
995@@ -1117,16 +1091,7 @@
996 i.putExtra(SERVICE_STATE, mInstallerState.ordinal());
997 sendBroadcast(i);
998 }
999-
1000- private void broadcastProgress(int val, String progress) {
1001- Intent i = new Intent(PROGRESS);
1002- i.putExtra(PROGRESS_EXTRA_INT, val);
1003- if (progress!= null) {
1004- i.putExtra(PROGRESS_EXTRA_TEXT, progress);
1005- }
1006- sendBroadcast(i);
1007- }
1008-
1009+
1010 /**
1011 * Check whether storage free space is enough.
1012 * @param downloadSize: download size from json. 0 means file already downloaded.
1013@@ -1161,6 +1126,7 @@
1014 }
1015 return null;
1016 }
1017+
1018 /**
1019 * Internal helper function to get current DOWNLOAD_VERSION even download is partial
1020 * @param context
1021@@ -1186,6 +1152,7 @@
1022 public static VersionInfo getInstalledVersion(Context c) {
1023 return getVersionWithPrefKey(c, PREF_KEY_INSTALLED_VERSION);
1024 }
1025+
1026 public static boolean isUbuntuInstalled(Context c) {
1027 SharedPreferences pref = c.getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE);
1028 if (VersionInfo.hasValidVersion(pref, PREF_KEY_INSTALLED_VERSION)) {
1029@@ -1194,9 +1161,111 @@
1030 }
1031 return false;
1032 }
1033+
1034+ /**
1035+ * check if update_command available for upgrade.
1036+ *
1037+ * @param c
1038+ * @return
1039+ */
1040+ public static boolean isUpgradeable(Context c) {
1041+ String cmd = c.getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE).getString(PREF_KEY_UPDATE_COMMAND, "");
1042+ return (cmd.startsWith("/cache/"));
1043+ }
1044+
1045+ /**
1046+ * check if recovery command is exist on the system.
1047+ * system-image in Ubuntu Touch downloaded new version of image at /cache/recovery.
1048+ * This function check if there is a ubuntu_command file in /cache/recovery.
1049+ *
1050+ * The ubuntu_command will be renamed or removed after installation.
1051+ *
1052+ * @return if there is upgradeable images stored in /cache.
1053+ */
1054+ public boolean findInstallCommand () {
1055+ String[] candidates = {
1056+ "/cache/recovery/ubuntu_command",
1057+ "/cache/ubunturecovery/ubuntu_command",
1058+ };
1059+ boolean ret = false;
1060+ for(String command: candidates) {
1061+ if(new File("/cache").canRead()) {
1062+ // if we have permission, we can read /cache.
1063+ File cmd = new File(command);
1064+ if(cmd.exists() && cmd.isFile()) {
1065+ Log.d(TAG, "Found upgrade command - " + cmd.getAbsoluteFile().toString());
1066+ // find the upgradeable file, stored into pref.
1067+ setUpdateCommand(cmd.getAbsolutePath());
1068+ ret = true;
1069+ }
1070+ } else {
1071+ // check the file with su
1072+ File workingFolder = new File(mRootOfWorkPath + "/" + TEMP_FOLDER);
1073+ if (!workingFolder.exists() && !workingFolder.mkdir()) {
1074+ Log.e(TAG, "can not create working folder");
1075+ ret = false;
1076+ }
1077+ try {
1078+ int r = executeSUCommands(new String[] {
1079+ String.format("%s %s\n", UPGRADECHECKER, command),
1080+ });
1081+ if(r == 1) {
1082+ Log.d(TAG, "Found upgradeable file - " + command);
1083+ setUpdateCommand(command);
1084+ ret = true;
1085+ }
1086+ } catch (EShellExecException e) {
1087+ ret = false;
1088+ }
1089+ }
1090+ }
1091+ if(ret) {
1092+ // FIXME we don't know what's the version in /cache.
1093+ SharedPreferences pref = getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE);
1094+ VersionInfo v = new VersionInfo(pref, PREF_KEY_INSTALLED_VERSION);
1095+ v.storeVersion(pref.edit(), PREF_KEY_DOWNLOADED_VERSION);
1096+ }
1097+ return ret;
1098+ }
1099+
1100+ /**
1101+ * set update command string stored in shared preferences.
1102+ * @file absolute file path of Ubuntu Command file.
1103+ */
1104+ private String getUpdateCommand(){
1105+ return getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE).getString(PREF_KEY_UPDATE_COMMAND, "");
1106+ }
1107+
1108+ /**
1109+ * set update command string stored in shared preferences.
1110+ * @file absolute file path of Ubuntu Command file.
1111+ */
1112+ private void setUpdateCommand(String file){
1113+ getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE).
1114+ edit().
1115+ putString(PREF_KEY_UPDATE_COMMAND, file).
1116+ commit();
1117+ }
1118+
1119+ /**
1120+ * clean update command string stored in shared preferences.
1121+ */
1122+ private void cleanUpdateCommand() {
1123+ this.setUpdateCommand("");
1124+ }
1125
1126+ private void broadcastProgress(int val, String progress) {
1127+ Intent i = new Intent(PROGRESS);
1128+ i.putExtra(PROGRESS_EXTRA_INT, val);
1129+ if (progress!= null) {
1130+ i.putExtra(PROGRESS_EXTRA_TEXT, progress);
1131+ }
1132+ sendBroadcast(i);
1133+ }
1134+
1135 /**
1136- * Check if there is downloaded release ready to install
1137+ * Check if there is downloaded release ready to install.
1138+ * If command file is not exist, reset downloaded version.
1139 * @param context
1140 * @return true if there is downloaded release ready to install
1141 */
1142@@ -1207,9 +1276,10 @@
1143 if (versionInfo.getDownloadedSize() != 0) return false;
1144
1145 String command = pref.getString(PREF_KEY_UPDATE_COMMAND, "");
1146+ Log.d(TAG, "checkifReadyToInstall");
1147 if (!command.equals("")) {
1148- File f = new File(command);
1149- if (f.exists()) {
1150+ if (new File(command).exists() || command.startsWith("/cache")) {
1151+ Log.d(TAG, "checkifReadyToInstall - found command file " + command);
1152 return true;
1153 } else {
1154 pref.edit().putString(PREF_KEY_UPDATE_COMMAND, "").commit();
1155
1156=== modified file 'src/com/canonical/ubuntu/installer/VersionInfo.java'
1157--- src/com/canonical/ubuntu/installer/VersionInfo.java 2013-12-24 03:50:41 +0000
1158+++ src/com/canonical/ubuntu/installer/VersionInfo.java 2013-12-26 07:18:46 +0000
1159@@ -5,7 +5,6 @@
1160
1161 /**
1162 * Version holder
1163- *
1164 */
1165 public class VersionInfo {
1166
1167@@ -109,9 +108,6 @@
1168 }
1169
1170 public static boolean hasValidVersion(SharedPreferences sp, String set) {
1171- int v = sp.getInt(set + VERSION, -1);
1172- String s1 = sp.getString(set + ALIAS, "");
1173- String s2 = sp.getString(set + JSON, "");
1174 return (-1 != sp.getInt(set + VERSION, -1));
1175 }
1176

Subscribers

People subscribed via source and target branches

to all changes: