Merge lp:~humpolec-team/humpolec/UbuntuInstaller-refactor into lp:humpolec
- UbuntuInstaller-refactor
- Merge into UbuntuInstaller
Proposed by
Ondrej Kubik
Status: | Merged |
---|---|
Merged at revision: | 72 |
Proposed branch: | lp:~humpolec-team/humpolec/UbuntuInstaller-refactor |
Merge into: | lp:humpolec |
Diff against target: |
5595 lines (+2511/-1557) (has conflicts) 37 files modified
.bzrignore (+1/-1) Android.mk (+1/-1) AndroidManifest.xml (+38/-12) ant.properties (+21/-0) assets/archive-master.tar.xz.asc (+0/-17) assets/system-image-upgrader (+28/-156) assets/u-reboot-app.tar.xz.asc (+0/-17) assets/upgrade-checker (+0/-16) build.xml (+35/-37) check-sdk.sh (+10/-0) make_release.sh (+0/-16) project.properties (+1/-1) res/layout/ubuntu_dualboot_launch.xml (+152/-104) res/menu/installer_menu.xml (+6/-10) res/menu/launcher_menu.xml (+19/-10) res/values/attrs.xml (+4/-4) res/values/colors.xml (+4/-4) res/values/ids.xml (+26/-0) res/values/strings.xml (+70/-14) res/values/styles.xml (+4/-4) src/com/canonical/ubuntu/installer/BaseActivity.java (+70/-0) src/com/canonical/ubuntu/installer/BootReceiver.java (+39/-0) src/com/canonical/ubuntu/installer/InstallActivity.java (+184/-160) src/com/canonical/ubuntu/installer/JsonChannelParser.java (+38/-16) src/com/canonical/ubuntu/installer/LaunchActivity.java (+216/-52) src/com/canonical/ubuntu/installer/NumberPickerDialog.java (+17/-3) src/com/canonical/ubuntu/installer/TextPickerDialog.java (+17/-1) src/com/canonical/ubuntu/installer/UbuntuInstallService.java (+1237/-723) src/com/canonical/ubuntu/installer/Utils.java (+245/-9) src/com/canonical/ubuntu/installer/VersionInfo.java (+0/-141) src/com/canonical/ubuntu/widget/UbuntuButton.java (+4/-4) src/com/canonical/ubuntu/widget/UbuntuCheckBox.java (+4/-4) src/com/canonical/ubuntu/widget/UbuntuCheckBoxPreference.java (+4/-4) src/com/canonical/ubuntu/widget/UbuntuEditText.java (+4/-4) src/com/canonical/ubuntu/widget/UbuntuEditTextPreference.java (+4/-4) src/com/canonical/ubuntu/widget/UbuntuPreference.java (+4/-4) src/com/canonical/ubuntu/widget/UbuntuTextView.java (+4/-4) Text conflict in AndroidManifest.xml |
To merge this branch: | bzr merge lp:~humpolec-team/humpolec/UbuntuInstaller-refactor |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ondrej Kubik | Approve | ||
Review via email: mp+222493@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2013-12-08 16:01:23 +0000 |
3 | +++ .bzrignore 2014-06-09 11:59:50 +0000 |
4 | @@ -1,6 +1,6 @@ |
5 | +.DS_Store |
6 | .project |
7 | local.properties |
8 | bin |
9 | gen |
10 | -android-ubuntu-launcher.apk |
11 | |
12 | |
13 | === modified file 'Android.mk' |
14 | --- Android.mk 2013-12-08 16:01:23 +0000 |
15 | +++ Android.mk 2014-06-09 11:59:50 +0000 |
16 | @@ -1,4 +1,4 @@ |
17 | -# UFA updater |
18 | +# Dualboot installer |
19 | LOCAL_PATH:= $(call my-dir) |
20 | |
21 | include $(CLEAR_VARS) |
22 | |
23 | === modified file 'AndroidManifest.xml' |
24 | --- AndroidManifest.xml 2014-03-05 15:35:14 +0000 |
25 | +++ AndroidManifest.xml 2014-06-09 11:59:50 +0000 |
26 | @@ -1,12 +1,34 @@ |
27 | <?xml version="1.0" encoding="utf-8"?> |
28 | +<!-- |
29 | +/* |
30 | + * This file is part of Ubuntu dualboot installer for Android. |
31 | + * Copyright 2013 Canonical Ltd. |
32 | + * |
33 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
34 | + * it under the terms of the GNU General Public License as published by |
35 | + * the Free Software Foundation. |
36 | + * |
37 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
38 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
39 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
40 | + * See the GNU General Public License for more details. |
41 | + * |
42 | + * You should have received a copy of the GNU General Public License |
43 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
44 | + */ |
45 | +--> |
46 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
47 | package="com.canonical.ubuntu.installer" |
48 | android:versionCode="20" |
49 | +<<<<<<< TREE |
50 | android:versionName="0.3" > |
51 | +======= |
52 | + android:versionName="1.0.0" > |
53 | +>>>>>>> MERGE-SOURCE |
54 | |
55 | <uses-sdk |
56 | android:minSdkVersion="17" |
57 | - android:targetSdkVersion="18" /> |
58 | + android:targetSdkVersion="19" /> |
59 | <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> |
60 | <uses-permission android:name="android.permission.GET_ACCOUNTS"/> |
61 | <uses-permission android:name="android.permission.ACCESS_SUPERUSER"/> |
62 | @@ -20,8 +42,6 @@ |
63 | <uses-permission android:name="android.permission.WAKE_LOCK" /> |
64 | <uses-permission android:name="android.permission.RECORD_AUDIO" /> |
65 | <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> |
66 | - <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" /> |
67 | - <uses-permission android:name="android.permission.REBOOT"/> |
68 | <uses-permission android:name="android.permission.ACCESS_SUPERUSER"/> |
69 | |
70 | <application |
71 | @@ -46,23 +66,29 @@ |
72 | android:label="@string/app_name"> |
73 | </activity> |
74 | |
75 | - <service android:name="com.canonical.ubuntu.installer.UbuntuInstallService"> |
76 | + <receiver android:name=".BootReceiver" > |
77 | + <intent-filter> |
78 | + <action android:name="android.intent.action.BOOT_COMPLETED" /> |
79 | + </intent-filter> |
80 | + </receiver> |
81 | + |
82 | + <service android:name="com.canonical.ubuntu.installer.UbuntuInstallService" |
83 | + android:exported="false"> |
84 | <intent-filter> |
85 | <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.GET_CHANNEL_LIST" /> |
86 | <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.DOWNLOAD_RELEASE" /> |
87 | - <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.CANCEL_DOWNLOAD" /> |
88 | + <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.DOWNLOAD_UPDATE" /> |
89 | <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.PAUSE_DOWNLOAD" /> |
90 | <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.RESUME_DOWNLOAD" /> |
91 | - <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.CLEAN_DOWNLOADED" /> |
92 | + <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.DELETE_DOWNLOAD" /> |
93 | <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.INSTALL_UBUNTU" /> |
94 | - <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.CANCEL_INSTALL" /> |
95 | <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.UINSTALL_UBUNTU" /> |
96 | - <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.CHECK_FOR_UPDATE" /> |
97 | - <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.DELETE_USER_DATA" /> |
98 | - <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.GET_SERVICE_STATE" /> |
99 | - <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.GET_PROGRESS_STATUS" /> |
100 | + <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.DELETE_UBUNTU_USER_DATA" /> |
101 | <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.REBOOT_UBUNTU" /> |
102 | - <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.IS_UBUNTU_UPGRADABLE" /> |
103 | + <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.UPDATE_STORAGE_USE" /> |
104 | + <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.CHECK_IF_UPDATE_AVAILABLE" /> |
105 | + <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.CHECK_PENDING_UPDATES" /> |
106 | + <action android:name="com.canonical.ubuntuinstaller.UbuntuInstallService.PREPARE_ANDROID_UPDATE" /> |
107 | </intent-filter> |
108 | </service> |
109 | </application> |
110 | |
111 | === added file 'ant.properties' |
112 | --- ant.properties 1970-01-01 00:00:00 +0000 |
113 | +++ ant.properties 2014-06-09 11:59:50 +0000 |
114 | @@ -0,0 +1,21 @@ |
115 | +# This file is used to override default values used by the Ant build system. |
116 | +# |
117 | +# This file must be checked in Version Control Systems, as it is |
118 | +# integral to the build system of your project. |
119 | + |
120 | +# This file is only used by the Ant script. |
121 | + |
122 | +# You can use this to override default values such as |
123 | +# 'source.dir' for the location of your java source folder and |
124 | +# 'out.dir' for the location of your output folder. |
125 | + |
126 | +# You can also use it define how the release builds are signed by declaring |
127 | +# the following properties: |
128 | +# 'key.store' for the location of your keystore and |
129 | +# 'key.alias' for the name of the key to use. |
130 | +# The password will be asked during the build when you use the 'release' target. |
131 | + |
132 | +java.encoding=UTF-8 |
133 | + |
134 | +key.store=../humpolec.keystore |
135 | +key.alias=humpolec |
136 | |
137 | === removed file 'assets/archive-master.tar.xz' |
138 | Binary files assets/archive-master.tar.xz 2013-12-08 16:01:23 +0000 and assets/archive-master.tar.xz 1970-01-01 00:00:00 +0000 differ |
139 | === removed file 'assets/archive-master.tar.xz.asc' |
140 | --- assets/archive-master.tar.xz.asc 2013-12-08 16:01:23 +0000 |
141 | +++ assets/archive-master.tar.xz.asc 1970-01-01 00:00:00 +0000 |
142 | @@ -1,17 +0,0 @@ |
143 | ------BEGIN PGP SIGNATURE----- |
144 | -Version: GnuPG v1.4.12 (GNU/Linux) |
145 | - |
146 | -iQIcBAABAgAGBQJRzXznAAoJEAv7hH8/Jy9b9MEP/iTl7lfFQNOu+bR+hRHOh40B |
147 | -trXCwTeKYGLL98h7pbqrqFD5QppGWZ5Kpyh5QeNB7yU8Jk5bcIQg3iTBg4kQhbjZ |
148 | -CvfBAk5goKDzHF+tx2HWFmHie3kxDlOQ39dWqr38Q78elC1VtRfiWQNbz7E2955D |
149 | -d5/Lo+THwKS0aYD8RR/wHbiEnIiOSxZLZo9Bdkxlty9LXbY16SUPY3R7POGdds0S |
150 | -OvQmsmFsjoD4b68aTjw0Fx12EQ1fDBycBmxNbgQ6E/xKf78Ttsp8gRaoopdr6odH |
151 | -FZWUCv0Vr7mrbSr8MrotydVRth5K/FJv4xnfTI9rY50PZqA72xFNfQyQa35/qfuZ |
152 | -3E+d9DdPk8KtovNCploTufRG5zvkXOn+rGJQCicLh4H2L7+YO5ZwHbDQFTDUrAhl |
153 | -0wlqaqUuwYOC7fxk3SHA3IINZ97LCUYfPWZRUUVOM2uia4BhI0TfRj09I+HnJM+I |
154 | -cNlfjmzCedlLjMwgBOw6tj1l3FEPl/aEwCTs1Oc7dc05JPDNcRqdks45NnSS/Xg7 |
155 | -pNHPS6wED0zYAKQeBDkji7Gf+9gR3eVWWbArSzbkqyCeWhgPyqwjTUQNMx6PIPNm |
156 | -0lszQWe50Y9mOuwcRd2gA293zVjsnr7NxOJPhgZsHB9fRaZtSg7vWVOo1jopkPPZ |
157 | -Vt1nrVFGkrss7EJ+Vc53 |
158 | -=Sszb |
159 | ------END PGP SIGNATURE----- |
160 | |
161 | === added file 'assets/recovery-remount.tar.xz' |
162 | Binary files assets/recovery-remount.tar.xz 1970-01-01 00:00:00 +0000 and assets/recovery-remount.tar.xz 2014-06-09 11:59:50 +0000 differ |
163 | === modified file 'assets/system-image-upgrader' |
164 | --- assets/system-image-upgrader 2014-01-08 06:21:14 +0000 |
165 | +++ assets/system-image-upgrader 2014-06-09 11:59:50 +0000 |
166 | @@ -9,7 +9,7 @@ |
167 | fi |
168 | |
169 | BUSYBOX=busybox |
170 | -COMMAND_FILE=$1.applying |
171 | +COMMAND_FILE=$1 |
172 | PRIVATE_DIR=$2 |
173 | REMOVE_LIST="$COMMAND_FILE" |
174 | TAR=u_tar |
175 | @@ -22,129 +22,14 @@ |
176 | |
177 | # switch to the update command folder, which has the images |
178 | cd $UPDATE_FOLDER |
179 | -mv $1 $1.applying |
180 | - |
181 | |
182 | # Functions |
183 | -verify_signature() { |
184 | - return 0 |
185 | - # $1 => validation keyring name |
186 | - # $2 => path to validate |
187 | - |
188 | - if [ ! -e $2 ]; then |
189 | - echo "File doesn't exist: $2" |
190 | - return 1 |
191 | - fi |
192 | - |
193 | - # Check against the blacklist |
194 | - if [ -e ${TMP}/system-image/blacklist/pubring.gpg ]; then |
195 | - export GNUPGHOME=${TMP}/system-image/blacklist/ |
196 | - if gpg --verify $2 >/dev/null 2>&1; then |
197 | - echo "File signed by a blacklisted key: $2" |
198 | - return 1 |
199 | - fi |
200 | - fi |
201 | - |
202 | - # Check against the keyring |
203 | - export GNUPGHOME=${TMP}/system-image/$1/ |
204 | - if [ ! -e "$GNUPGHOME" ]; then |
205 | - echo "Keyring doesn't exist: $1" |
206 | - return 1 |
207 | - fi |
208 | - |
209 | - if gpg --verify $2 >/dev/null 2>&1; then |
210 | - return 0 |
211 | - fi |
212 | -} |
213 | - |
214 | -install_keyring() { |
215 | - # $1 => full path to tarball |
216 | - # $2 => full path to signature |
217 | - |
218 | - # Some basic checks |
219 | - if [ ! -e "$1" ] || [ ! -e "$2" ]; then |
220 | - echo "Missing keyring files: $1 => $2" |
221 | - return 1 |
222 | - fi |
223 | - |
224 | - # Unpacking |
225 | - TMPDIR=$($BUSYBOX mktemp -d ${TMP}/tempdir.XXXXXXXX) |
226 | - cd $TMPDIR |
227 | - cat $1 | $BUSYBOX unxz | $TAR xf - |
228 | - if [ ! -e keyring.json ] || [ ! -e keyring.gpg ]; then |
229 | - rm -Rf $TMPDIR |
230 | - echo "Invalid keyring: $1" |
231 | - return 1 |
232 | - fi |
233 | - |
234 | - # Extract the expiry |
235 | - keyring_expiry=$(grep "^ \"expiry\": " keyring.json | $BUSYBOX cut -d: -f2 | $BUSYBOX sed -e "s/[ \",]//g") |
236 | - if [ -n "$keyring_expiry" ] && [ "$keyring_expiry" -lt "$(date +%s)" ]; then |
237 | - rm -Rf $TMPDIR |
238 | - echo "Keyring expired: $1" |
239 | - return 1 |
240 | - fi |
241 | - |
242 | - # Extract the keyring type |
243 | - keyring_type=$(grep "^ \"type\": " keyring.json | $BUSYBOX cut -d: -f2 | $BUSYBOX sed -e "s/[, \"]//g") |
244 | - if [ -z "$keyring_type" ]; then |
245 | - rm -Rf $TMPDIR |
246 | - echo "Missing keyring type: $1" |
247 | - return 1 |
248 | - fi |
249 | - |
250 | - if [ -e ${TMP}/system-image/$keyring_type ]; then |
251 | - rm -Rf $TMPDIR |
252 | - echo "Keyring already loaded: $1" |
253 | - return 1 |
254 | - fi |
255 | - |
256 | - signer="unknown" |
257 | - case "$keyring_type" in |
258 | - archive-master) |
259 | - signer="" |
260 | - ;; |
261 | - |
262 | - image-master) |
263 | - signer="archive-master" |
264 | - ;; |
265 | - |
266 | - image-signing|blacklist) |
267 | - signer="image-master" |
268 | - ;; |
269 | - |
270 | - device-signing) |
271 | - signer="image-signing" |
272 | - ;; |
273 | - esac |
274 | - |
275 | - if [ -n "$signer" ] && ! verify_signature $signer $2; then |
276 | - rm -Rf $TMPDIR |
277 | - echo "Invalid signature: $1" |
278 | - return 1 |
279 | - fi |
280 | - |
281 | - mkdir ${TMP}/system-image/$keyring_type |
282 | - chmod 700 ${TMP}/system-image/$keyring_type |
283 | - mv $TMPDIR/keyring.gpg ${TMP}/system-image/$keyring_type/pubring.gpg |
284 | - chmod 600 ${TMP}/system-image/$keyring_type/pubring.gpg |
285 | - chown 0:0 ${TMP}/system-image/$keyring_type/pubring.gpg |
286 | - rm -Rf $TMPDIR |
287 | - return 0 |
288 | -} |
289 | - |
290 | -# print out if we will need to create SWAP file |
291 | -if [ ! -e /data/SWAP.img ]; then |
292 | - echo "SWAP-file-missing" >&2 |
293 | -fi |
294 | + |
295 | |
296 | # Initialize GPG |
297 | rm -Rf ${TMP}/system-image |
298 | mkdir -p ${TMP}/system-image |
299 | -if [ -e ${PWD}/archive-master.tar.xz ]; then |
300 | - echo "Loading keyring: archive-master.tar.xz" |
301 | - install_keyring ${PWD}/archive-master.tar.xz ${PWD}/archive-master.tar.xz.asc |
302 | -fi |
303 | + |
304 | |
305 | # Process the command file |
306 | FULL_IMAGE=0 |
307 | @@ -159,11 +44,14 @@ |
308 | system) |
309 | FULL_IMAGE=1 |
310 | rm -f /data/system.img |
311 | + echo "Creating new system filesystem" |
312 | $BUSYBOX dd if=/dev/zero of=/data/system.img seek=500K bs=4096 count=1 |
313 | $BUSYBOX mkfs.ext2 -F /data/system.img |
314 | + echo "New system filesystem created" |
315 | ;; |
316 | |
317 | data) |
318 | + # formatting data partion -> just detele ubuntu bits |
319 | rm -f /data/SWAP.img |
320 | rm -Rf /data/system-data |
321 | rm -Rf /data/user-data |
322 | @@ -176,25 +64,11 @@ |
323 | ;; |
324 | |
325 | load_keyring) |
326 | - if [ ! -e "$UPDATE_FOLDER/$2" ] || [ ! -e "$UPDATE_FOLDER/$3" ]; then |
327 | - echo "Skipping missing file: $2" |
328 | - continue |
329 | - fi |
330 | - REMOVE_LIST="$REMOVE_LIST $UPDATE_FOLDER/$2 $UPDATE_FOLDER/$3" |
331 | - |
332 | - echo "Loading keyring: $2" |
333 | - install_keyring $UPDATE_FOLDER/$2 $UPDATE_FOLDER/$3 |
334 | - |
335 | - if [ -e ${TMP}/system-image/image-master/pubring.gpg ] && \ |
336 | - [ ! -e ${TMP}/system-image/blacklist/pubring.gpg ] && \ |
337 | - [ -e /data/system-data/var/lib/system-image/blacklist.tar.xz ] && \ |
338 | - [ -e /data/system-data/var/lib/system-image/blacklist.tar.xz.asc ]; then |
339 | - echo "Loading blacklist keyring" |
340 | - install_keyring /data/system-data/var/lib/system-image/blacklist.tar.xz /data/system-data/var/lib/system-image/blacklist.tar.xz.asc |
341 | - fi |
342 | + echo "Loading keys: $2 $3" |
343 | ;; |
344 | |
345 | mount) |
346 | + echo "Mounting: $2" |
347 | case "$2" in |
348 | system) |
349 | mkdir -p /cache/system |
350 | @@ -208,8 +82,11 @@ |
351 | ;; |
352 | |
353 | unmount) |
354 | + echo "Unmounting: $2" |
355 | case "$2" in |
356 | system) |
357 | + # print out version info |
358 | + cat /cache/system/etc/system-image/channel.ini || true |
359 | aloopmount umount /cache/system && echo . |
360 | rmdir /cache/system |
361 | ;; |
362 | @@ -221,17 +98,13 @@ |
363 | ;; |
364 | |
365 | update) |
366 | - if [ ! -e "$UPDATE_FOLDER/$2" ] || [ ! -e "$UPDATE_FOLDER/$3" ]; then |
367 | + if [ ! -e "$UPDATE_FOLDER/$2" ]; then |
368 | echo "Skipping missing file: $2" |
369 | continue |
370 | fi |
371 | |
372 | - REMOVE_LIST="$REMOVE_LIST $UPDATE_FOLDER/$2 $UPDATE_FOLDER/$3" |
373 | - if ! verify_signature device-signing $UPDATE_FOLDER/$2 && \ |
374 | - ! verify_signature image-signing $UPDATE_FOLDER/$2; then |
375 | - echo "Invalid signature" |
376 | - continue |
377 | - fi |
378 | + REMOVE_LIST="$REMOVE_LIST $UPDATE_FOLDER/$2" |
379 | + |
380 | |
381 | echo "Applying update: $2" |
382 | cd /cache |
383 | @@ -239,17 +112,19 @@ |
384 | |
385 | # Start by removing any file listed in "removed" |
386 | if [ "$FULL_IMAGE" != "1" ]; then |
387 | - cat $UPDATE_FOLDER/$2 | $BUSYBOX unxz | $TAR xf - removed >/dev/null 2>&1 || true |
388 | + $BUSYBOX cat $UPDATE_FOLDER/$2 | $BUSYBOX unxz | $TAR --checkpoint=400 -xf - removed >/dev/null || true |
389 | if [ -e removed ]; then |
390 | - while read file; do |
391 | + echo "Removing old files..." |
392 | + while read file; do |
393 | rm -Rf $file |
394 | done < removed |
395 | fi |
396 | rm -f removed |
397 | + echo "Adding new files..." |
398 | fi |
399 | |
400 | # Unpack everything else on top of the system partition |
401 | - cat $UPDATE_FOLDER/$2 | $BUSYBOX unxz | $TAR --checkpoint=200 -xf - |
402 | + $BUSYBOX cat $UPDATE_FOLDER/$2 | $BUSYBOX unxz | $TAR --checkpoint=200 -xf - |
403 | rm -f removed |
404 | |
405 | if [ -e "partitions/boot.img" ]; then |
406 | @@ -281,20 +156,17 @@ |
407 | |
408 | # Remove the update files |
409 | for file in $REMOVE_LIST; do |
410 | - echo rm $file |
411 | + rm $file |
412 | done |
413 | |
414 | -# Create the SWAP image if missing |
415 | -if [ ! -e /data/SWAP.img ]; then |
416 | - echo "Creating SWAP device." |
417 | - echo "SWAP Checkpoint 0" >&2 |
418 | - # create swap file in private folder, so service can watch progress |
419 | - dd if=/dev/zero of=$PRIVATE_DIR/SWAP.img bs=4096 count=131072 |
420 | - echo "Moving SWAP device to final destination" >&2 |
421 | - mv $PRIVATE_DIR/SWAP.img /data/ |
422 | - echo "Calling mkswap on /data/SWAP.img" >&2 |
423 | - $BUSYBOX mkswap /data/SWAP.img |
424 | -fi |
425 | +# Ensure we have sane permissions |
426 | +chmod 600 /data/system.img |
427 | +chown 0:0 /data/system.img |
428 | + |
429 | +# calculate sizes |
430 | +busybox du -sm /data/system.img || true |
431 | +busybox du -sm /data/system-data || true |
432 | +busybox du -sm /data/user-data || true |
433 | |
434 | touch /data/.last_update || true |
435 | sync |
436 | |
437 | === removed file 'assets/u-reboot-app.tar.xz.asc' |
438 | --- assets/u-reboot-app.tar.xz.asc 2013-12-12 02:02:35 +0000 |
439 | +++ assets/u-reboot-app.tar.xz.asc 1970-01-01 00:00:00 +0000 |
440 | @@ -1,17 +0,0 @@ |
441 | ------BEGIN PGP SIGNATURE----- |
442 | -Version: GnuPG v1.4.12 (GNU/Linux) |
443 | - |
444 | -iQIcBAABAgAGBQJRzXznAAoJEAv7hH8/Jy9b9MEP/iTl7lfFQNOu+bR+hRHOh40B |
445 | -trXCwTeKYGLL98h7pbqrqFD5QppGWZ5Kpyh5QeNB7yU8Jk5bcIQg3iTBg4kQhbjZ |
446 | -CvfBAk5goKDzHF+tx2HWFmHie3kxDlOQ39dWqr38Q78elC1VtRfiWQNbz7E2955D |
447 | -d5/Lo+THwKS0aYD8RR/wHbiEnIiOSxZLZo9Bdkxlty9LXbY16SUPY3R7POGdds0S |
448 | -OvQmsmFsjoD4b68aTjw0Fx12EQ1fDBycBmxNbgQ6E/xKf78Ttsp8gRaoopdr6odH |
449 | -FZWUCv0Vr7mrbSr8MrotydVRth5K/FJv4xnfTI9rY50PZqA72xFNfQyQa35/qfuZ |
450 | -3E+d9DdPk8KtovNCploTufRG5zvkXOn+rGJQCicLh4H2L7+YO5ZwHbDQFTDUrAhl |
451 | -0wlqaqUuwYOC7fxk3SHA3IINZ97LCUYfPWZRUUVOM2uia4BhI0TfRj09I+HnJM+I |
452 | -cNlfjmzCedlLjMwgBOw6tj1l3FEPl/aEwCTs1Oc7dc05JPDNcRqdks45NnSS/Xg7 |
453 | -pNHPS6wED0zYAKQeBDkji7Gf+9gR3eVWWbArSzbkqyCeWhgPyqwjTUQNMx6PIPNm |
454 | -0lszQWe50Y9mOuwcRd2gA293zVjsnr7NxOJPhgZsHB9fRaZtSg7vWVOo1jopkPPZ |
455 | -Vt1nrVFGkrss7EJ+Vc53 |
456 | -=Sszb |
457 | ------END PGP SIGNATURE----- |
458 | |
459 | === removed file 'assets/upgrade-checker' |
460 | --- assets/upgrade-checker 2013-12-25 11:32:41 +0000 |
461 | +++ assets/upgrade-checker 1970-01-01 00:00:00 +0000 |
462 | @@ -1,16 +0,0 @@ |
463 | -#!/system/bin/sh |
464 | -# Copyright (C) 2013 Canonical Ltd. |
465 | -# |
466 | -# Check if ubuntu_command exist |
467 | -# print the path and exit 0 if found. |
468 | - |
469 | -FILES=$@ |
470 | - |
471 | -for file in $FILES ; do |
472 | - if [[ -f $file ]] ; then |
473 | - echo $file |
474 | - exit 1 |
475 | - fi |
476 | -done |
477 | - |
478 | -exit 0 |
479 | |
480 | === modified file 'build.xml' |
481 | --- build.xml 2013-12-08 16:01:23 +0000 |
482 | +++ build.xml 2014-06-09 11:59:50 +0000 |
483 | @@ -1,31 +1,40 @@ |
484 | <?xml version="1.0" encoding="UTF-8"?> |
485 | -<project name="MainActivity" default="help"> |
486 | - |
487 | - <!-- The local.properties file is created and updated by the 'android' tool. |
488 | - It contains the path to the SDK. It should *NOT* be checked into |
489 | - Version Control Systems. --> |
490 | +<project name="UbuntuInstaller" default="help"> |
491 | + |
492 | + <description> |
493 | + *** Humpolec - Ubuntu Dual Boot for Android *** |
494 | + |
495 | + http://launchpad.net/humpolec |
496 | + |
497 | + Ubuntu Dual Boot is provided to developers who want to contribute to development |
498 | + of Ubuntu for Phones and give them an ability to run Ubuntu and Android on |
499 | + a single device. It is not intended to be used by regular users. |
500 | + |
501 | + Make sure you have Android SDK installed! |
502 | + |
503 | + Contact: |
504 | + Ondrej Kubik ondrej.kubik@canonical.com |
505 | + Michal Karnicki michal.karnicki@canonical.com |
506 | + </description> |
507 | + |
508 | + <!-- Check if android is present. --> |
509 | + <exec executable="./check-sdk.sh" failonerror="true"> |
510 | + </exec> |
511 | + |
512 | + <property file="project.properties" /> |
513 | + |
514 | + <exec executable="android"> |
515 | + <arg value="update" /> |
516 | + <arg value="project" /> |
517 | + <arg value="-p" /> |
518 | + <arg value="." /> |
519 | + <arg value="-t" /> |
520 | + <arg value="${target}" /> |
521 | + <!-- Watch out: using name argument will ignore the custom build.xml version-tag! --> |
522 | + </exec> |
523 | + |
524 | <property file="local.properties" /> |
525 | |
526 | - <!-- The ant.properties file can be created by you. It is only edited by the |
527 | - 'android' tool to add properties to it. |
528 | - This is the place to change some Ant specific build properties. |
529 | - Here are some properties you may want to change/update: |
530 | - |
531 | - source.dir |
532 | - The name of the source directory. Default is 'src'. |
533 | - out.dir |
534 | - The name of the output directory. Default is 'bin'. |
535 | - |
536 | - For other overridable properties, look at the beginning of the rules |
537 | - files in the SDK, at tools/ant/build.xml |
538 | - |
539 | - Properties related to the SDK location or the project target should |
540 | - be updated using the 'android' tool with the 'update' action. |
541 | - |
542 | - This file is an integral part of the build system for your |
543 | - application and should be checked into Version Control Systems. |
544 | - |
545 | - --> |
546 | <property file="ant.properties" /> |
547 | |
548 | <!-- if sdk.dir was not set from one of the property file, then |
549 | @@ -37,17 +46,6 @@ |
550 | <isset property="env.ANDROID_HOME" /> |
551 | </condition> |
552 | |
553 | - <!-- The project.properties file is created and updated by the 'android' |
554 | - tool, as well as ADT. |
555 | - |
556 | - This contains project specific properties such as project target, and library |
557 | - dependencies. Lower level build properties are stored in ant.properties |
558 | - (or in .classpath for Eclipse projects). |
559 | - |
560 | - This file is an integral part of the build system for your |
561 | - application and should be checked into Version Control Systems. --> |
562 | - <loadproperties srcFile="project.properties" /> |
563 | - |
564 | <!-- quick check on sdk.dir --> |
565 | <fail |
566 | message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable." |
567 | @@ -86,7 +84,7 @@ |
568 | In all cases you must update the value of version-tag below to read 'custom' instead of an integer, |
569 | in order to avoid having your file be overridden by tools such as "android update project" |
570 | --> |
571 | - <!-- version-tag: 1 --> |
572 | + <!-- version-tag: custom --> |
573 | <import file="${sdk.dir}/tools/ant/build.xml" /> |
574 | |
575 | </project> |
576 | |
577 | === added file 'check-sdk.sh' |
578 | --- check-sdk.sh 1970-01-01 00:00:00 +0000 |
579 | +++ check-sdk.sh 2014-06-09 11:59:50 +0000 |
580 | @@ -0,0 +1,10 @@ |
581 | +#!/bin/bash |
582 | + |
583 | +ANDROIDBIN=$(which android) |
584 | +if test -z "${ANDROIDBIN}"; then |
585 | + echo "Android SDK tools not in PATH, fix with:" >&2 |
586 | + echo " PATH=\$PATH:/PathToSDK/tools" >&2 |
587 | + exit 1 |
588 | +fi |
589 | + |
590 | +exit 0 |
591 | |
592 | === removed file 'make_release.sh' |
593 | --- make_release.sh 2013-12-20 03:39:53 +0000 |
594 | +++ make_release.sh 1970-01-01 00:00:00 +0000 |
595 | @@ -1,16 +0,0 @@ |
596 | - #!/sbin/sh |
597 | - KEY=$1 |
598 | - if [[ -z "$KEY" ]]; then |
599 | - echo "Pass path to the keystore" |
600 | - exit -1 |
601 | - fi |
602 | - echo "Release tool, using key" |
603 | - echo "Getting ready for build" |
604 | - android update project --path . |
605 | - echo "Removing old release" |
606 | - rm -rf bin/ |
607 | - ant release |
608 | - echo "Signing build" |
609 | - jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore $KEY bin/MainActivity-release-unsigned.apk humpolec |
610 | - mv bin/MainActivity-release-unsigned.apk bin/UbuntuInstaller.apk |
611 | - echo "Signed relase is at bin/UbuntuInstaller.apk" |
612 | \ No newline at end of file |
613 | |
614 | === modified file 'project.properties' |
615 | --- project.properties 2013-12-12 02:02:35 +0000 |
616 | +++ project.properties 2014-06-09 11:59:50 +0000 |
617 | @@ -11,4 +11,4 @@ |
618 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt |
619 | |
620 | # Project target. |
621 | -target=Google Inc.:Google APIs:19 |
622 | +target=android-19 |
623 | |
624 | === added file 'res/drawable-hdpi/ic_action_discard.png' |
625 | Binary files res/drawable-hdpi/ic_action_discard.png 1970-01-01 00:00:00 +0000 and res/drawable-hdpi/ic_action_discard.png 2014-06-09 11:59:50 +0000 differ |
626 | === added file 'res/drawable-hdpi/ic_action_refresh.png' |
627 | Binary files res/drawable-hdpi/ic_action_refresh.png 1970-01-01 00:00:00 +0000 and res/drawable-hdpi/ic_action_refresh.png 2014-06-09 11:59:50 +0000 differ |
628 | === added file 'res/drawable-hdpi/ic_action_share.png' |
629 | Binary files res/drawable-hdpi/ic_action_share.png 1970-01-01 00:00:00 +0000 and res/drawable-hdpi/ic_action_share.png 2014-06-09 11:59:50 +0000 differ |
630 | === added directory 'res/drawable-ldpi' |
631 | === added file 'res/drawable-mdpi/ic_action_discard.png' |
632 | Binary files res/drawable-mdpi/ic_action_discard.png 1970-01-01 00:00:00 +0000 and res/drawable-mdpi/ic_action_discard.png 2014-06-09 11:59:50 +0000 differ |
633 | === added file 'res/drawable-mdpi/ic_action_refresh.png' |
634 | Binary files res/drawable-mdpi/ic_action_refresh.png 1970-01-01 00:00:00 +0000 and res/drawable-mdpi/ic_action_refresh.png 2014-06-09 11:59:50 +0000 differ |
635 | === added file 'res/drawable-mdpi/ic_action_share.png' |
636 | Binary files res/drawable-mdpi/ic_action_share.png 1970-01-01 00:00:00 +0000 and res/drawable-mdpi/ic_action_share.png 2014-06-09 11:59:50 +0000 differ |
637 | === added file 'res/drawable-xhdpi/ic_action_discard.png' |
638 | Binary files res/drawable-xhdpi/ic_action_discard.png 1970-01-01 00:00:00 +0000 and res/drawable-xhdpi/ic_action_discard.png 2014-06-09 11:59:50 +0000 differ |
639 | === added file 'res/drawable-xhdpi/ic_action_refresh.png' |
640 | Binary files res/drawable-xhdpi/ic_action_refresh.png 1970-01-01 00:00:00 +0000 and res/drawable-xhdpi/ic_action_refresh.png 2014-06-09 11:59:50 +0000 differ |
641 | === added file 'res/drawable-xhdpi/ic_action_share.png' |
642 | Binary files res/drawable-xhdpi/ic_action_share.png 1970-01-01 00:00:00 +0000 and res/drawable-xhdpi/ic_action_share.png 2014-06-09 11:59:50 +0000 differ |
643 | === added file 'res/drawable-xhdpi/ic_stat_notify_ubuntu.png' |
644 | Binary files res/drawable-xhdpi/ic_stat_notify_ubuntu.png 1970-01-01 00:00:00 +0000 and res/drawable-xhdpi/ic_stat_notify_ubuntu.png 2014-06-09 11:59:50 +0000 differ |
645 | === added file 'res/drawable-xxhdpi/ic_action_discard.png' |
646 | Binary files res/drawable-xxhdpi/ic_action_discard.png 1970-01-01 00:00:00 +0000 and res/drawable-xxhdpi/ic_action_discard.png 2014-06-09 11:59:50 +0000 differ |
647 | === added file 'res/drawable-xxhdpi/ic_action_refresh.png' |
648 | Binary files res/drawable-xxhdpi/ic_action_refresh.png 1970-01-01 00:00:00 +0000 and res/drawable-xxhdpi/ic_action_refresh.png 2014-06-09 11:59:50 +0000 differ |
649 | === added file 'res/drawable-xxhdpi/ic_action_share.png' |
650 | Binary files res/drawable-xxhdpi/ic_action_share.png 1970-01-01 00:00:00 +0000 and res/drawable-xxhdpi/ic_action_share.png 2014-06-09 11:59:50 +0000 differ |
651 | === modified file 'res/layout/ubuntu_dualboot_launch.xml' |
652 | --- res/layout/ubuntu_dualboot_launch.xml 2013-12-12 02:02:35 +0000 |
653 | +++ res/layout/ubuntu_dualboot_launch.xml 2014-06-09 11:59:50 +0000 |
654 | @@ -10,18 +10,6 @@ |
655 | android:background="#FFFFFF" |
656 | android:orientation="vertical" > |
657 | |
658 | - <com.canonical.ubuntu.widget.UbuntuButton |
659 | - android:id="@+id/download" |
660 | - style="@style/Button.Grey" |
661 | - android:layout_width="match_parent" |
662 | - android:layout_height="wrap_content" |
663 | - android:layout_alignParentBottom="true" |
664 | - android:layout_gravity="center_horizontal" |
665 | - android:adjustViewBounds="true" |
666 | - android:text="hi" |
667 | - android:textColor="@color/text" |
668 | - u1f:customFont="Ubuntu-R.ttf" /> |
669 | - |
670 | <com.canonical.ubuntu.widget.UbuntuTextView |
671 | android:id="@+id/title" |
672 | android:layout_width="wrap_content" |
673 | @@ -54,7 +42,7 @@ |
674 | android:layout_alignParentLeft="true" |
675 | android:layout_centerHorizontal="true" |
676 | android:layout_margin="2dp" |
677 | - android:text="Info:" |
678 | + android:text="Build number:" |
679 | android:textAppearance="?android:attr/textAppearanceMedium" |
680 | android:textColor="@color/ubuntuorange" |
681 | android:textStyle="bold" |
682 | @@ -84,7 +72,7 @@ |
683 | android:layout_alignParentLeft="true" |
684 | android:layout_centerHorizontal="true" |
685 | android:layout_margin="2dp" |
686 | - android:text="Info:" |
687 | + android:text="Channel:" |
688 | android:textAppearance="?android:attr/textAppearanceMedium" |
689 | android:textColor="@color/ubuntuorange" |
690 | android:textStyle="bold" |
691 | @@ -97,7 +85,7 @@ |
692 | android:layout_margin="2dp" |
693 | android:layout_toRightOf="@id/channel_label" |
694 | android:singleLine="true" |
695 | - android:text="add version" |
696 | + android:text="add channel" |
697 | android:textAppearance="?android:attr/textAppearanceMedium" |
698 | android:textColor="@color/text" |
699 | u1f:customFont="Ubuntu-R.ttf" /> |
700 | @@ -108,13 +96,43 @@ |
701 | android:layout_height="wrap_content" > |
702 | |
703 | <com.canonical.ubuntu.widget.UbuntuTextView |
704 | + android:id="@+id/ref_channel_label" |
705 | + android:layout_width="wrap_content" |
706 | + android:layout_height="wrap_content" |
707 | + android:layout_alignParentLeft="true" |
708 | + android:layout_centerHorizontal="true" |
709 | + android:layout_margin="2dp" |
710 | + android:text="Target Channel:" |
711 | + android:textAppearance="?android:attr/textAppearanceMedium" |
712 | + android:textColor="@color/ubuntuorange" |
713 | + android:textStyle="bold" |
714 | + u1f:customFont="Ubuntu-R.ttf" /> |
715 | + |
716 | + <com.canonical.ubuntu.widget.UbuntuTextView |
717 | + android:id="@+id/ref_channel" |
718 | + android:layout_width="wrap_content" |
719 | + android:layout_height="wrap_content" |
720 | + android:layout_margin="2dp" |
721 | + android:layout_toRightOf="@id/ref_channel_label" |
722 | + android:singleLine="true" |
723 | + android:text="add channel" |
724 | + android:textAppearance="?android:attr/textAppearanceMedium" |
725 | + android:textColor="@color/text" |
726 | + u1f:customFont="Ubuntu-R.ttf" /> |
727 | + </RelativeLayout> |
728 | + |
729 | + <RelativeLayout |
730 | + android:layout_width="wrap_content" |
731 | + android:layout_height="wrap_content" > |
732 | + |
733 | + <com.canonical.ubuntu.widget.UbuntuTextView |
734 | android:id="@+id/description_label" |
735 | android:layout_width="wrap_content" |
736 | android:layout_height="wrap_content" |
737 | android:layout_alignParentLeft="true" |
738 | android:layout_centerHorizontal="true" |
739 | android:layout_margin="2dp" |
740 | - android:text="Info:" |
741 | + android:text="Description:" |
742 | android:textAppearance="?android:attr/textAppearanceMedium" |
743 | android:textColor="@color/ubuntuorange" |
744 | android:textStyle="bold" |
745 | @@ -125,43 +143,14 @@ |
746 | android:layout_width="wrap_content" |
747 | android:layout_height="wrap_content" |
748 | android:layout_margin="2dp" |
749 | - android:layout_toRightOf="@id/description_label" |
750 | - android:singleLine="true" |
751 | - android:text="add version" |
752 | - android:textAppearance="?android:attr/textAppearanceMedium" |
753 | - android:textColor="@color/text" |
754 | - u1f:customFont="Ubuntu-R.ttf" /> |
755 | - </RelativeLayout> |
756 | - |
757 | - <RelativeLayout |
758 | - android:layout_width="wrap_content" |
759 | - android:layout_height="wrap_content" > |
760 | - |
761 | - <com.canonical.ubuntu.widget.UbuntuTextView |
762 | - android:id="@+id/total_label" |
763 | - android:layout_width="wrap_content" |
764 | - android:layout_height="wrap_content" |
765 | - android:layout_alignParentLeft="true" |
766 | - android:layout_centerHorizontal="true" |
767 | - android:layout_margin="2dp" |
768 | - android:text="Info:" |
769 | - android:textAppearance="?android:attr/textAppearanceMedium" |
770 | - android:textColor="@color/ubuntuorange" |
771 | - android:textStyle="bold" |
772 | - u1f:customFont="Ubuntu-R.ttf" /> |
773 | - |
774 | - <com.canonical.ubuntu.widget.UbuntuTextView |
775 | - android:id="@+id/total" |
776 | - android:layout_width="wrap_content" |
777 | - android:layout_height="wrap_content" |
778 | - android:layout_margin="2dp" |
779 | - android:layout_toRightOf="@id/total_label" |
780 | - android:singleLine="true" |
781 | - android:text="add version" |
782 | - android:textAppearance="?android:attr/textAppearanceMedium" |
783 | - android:textColor="@color/text" |
784 | - u1f:customFont="Ubuntu-R.ttf" /> |
785 | - </RelativeLayout> |
786 | + android:layout_below="@id/description_label" |
787 | + android:singleLine="true" |
788 | + android:text="add description" |
789 | + android:textAppearance="?android:attr/textAppearanceMedium" |
790 | + android:textColor="@color/text" |
791 | + u1f:customFont="Ubuntu-R.ttf" /> |
792 | + </RelativeLayout> |
793 | + |
794 | |
795 | <View |
796 | android:id="@+id/divider" |
797 | @@ -175,61 +164,120 @@ |
798 | android:layout_marginLeft="10dp" > |
799 | |
800 | <com.canonical.ubuntu.widget.UbuntuTextView |
801 | - android:id="@+id/app_label" |
802 | - android:layout_width="wrap_content" |
803 | - android:layout_height="wrap_content" |
804 | - android:layout_alignParentLeft="true" |
805 | - android:layout_centerHorizontal="true" |
806 | - android:layout_margin="2dp" |
807 | - android:text="Info:" |
808 | - android:textAppearance="?android:attr/textAppearanceMedium" |
809 | - android:textColor="@color/text" |
810 | - android:textStyle="bold" |
811 | - u1f:customFont="Ubuntu-R.ttf" /> |
812 | - |
813 | - <com.canonical.ubuntu.widget.UbuntuTextView |
814 | - android:id="@+id/appsize" |
815 | - android:layout_width="wrap_content" |
816 | - android:layout_height="wrap_content" |
817 | - android:layout_margin="2dp" |
818 | - android:layout_toRightOf="@id/app_label" |
819 | - android:singleLine="true" |
820 | - android:text="add version" |
821 | - android:textAppearance="?android:attr/textAppearanceMedium" |
822 | - android:textColor="@color/text" |
823 | - u1f:customFont="Ubuntu-R.ttf" /> |
824 | - </RelativeLayout> |
825 | - |
826 | - <RelativeLayout |
827 | - android:layout_width="wrap_content" |
828 | - android:layout_height="wrap_content" |
829 | - android:layout_marginLeft="10dp" > |
830 | - |
831 | - <com.canonical.ubuntu.widget.UbuntuTextView |
832 | - android:id="@+id/data_label" |
833 | - android:layout_width="wrap_content" |
834 | - android:layout_height="wrap_content" |
835 | - android:layout_alignParentLeft="true" |
836 | - android:layout_centerHorizontal="true" |
837 | - android:layout_margin="2dp" |
838 | - android:text="Info:" |
839 | - android:textAppearance="?android:attr/textAppearanceMedium" |
840 | - android:textColor="@color/text" |
841 | - android:textStyle="bold" |
842 | - u1f:customFont="Ubuntu-R.ttf" /> |
843 | - |
844 | - <com.canonical.ubuntu.widget.UbuntuTextView |
845 | - android:id="@+id/datasize" |
846 | - android:layout_width="wrap_content" |
847 | - android:layout_height="wrap_content" |
848 | - android:layout_margin="2dp" |
849 | - android:layout_toRightOf="@id/data_label" |
850 | - android:singleLine="true" |
851 | - android:text="add version" |
852 | + android:id="@+id/rootfs_label" |
853 | + android:layout_width="wrap_content" |
854 | + android:layout_height="wrap_content" |
855 | + android:layout_alignParentLeft="true" |
856 | + android:layout_centerHorizontal="true" |
857 | + android:layout_margin="2dp" |
858 | + android:text="rootfs:" |
859 | + android:textAppearance="?android:attr/textAppearanceMedium" |
860 | + android:textColor="@color/text" |
861 | + android:textStyle="bold" |
862 | + u1f:customFont="Ubuntu-R.ttf" /> |
863 | + |
864 | + <com.canonical.ubuntu.widget.UbuntuTextView |
865 | + android:id="@+id/rootfssize" |
866 | + android:layout_width="wrap_content" |
867 | + android:layout_height="wrap_content" |
868 | + android:layout_margin="2dp" |
869 | + android:layout_toRightOf="@id/rootfs_label" |
870 | + android:singleLine="true" |
871 | + android:text="used MB" |
872 | + android:textAppearance="?android:attr/textAppearanceMedium" |
873 | + android:textColor="@color/text" |
874 | + u1f:customFont="Ubuntu-R.ttf" /> |
875 | + </RelativeLayout> |
876 | + |
877 | + |
878 | + |
879 | + <RelativeLayout |
880 | + android:layout_width="wrap_content" |
881 | + android:layout_height="wrap_content" |
882 | + android:layout_marginLeft="10dp" > |
883 | + |
884 | + <com.canonical.ubuntu.widget.UbuntuTextView |
885 | + android:id="@+id/system_data_label" |
886 | + android:layout_width="wrap_content" |
887 | + android:layout_height="wrap_content" |
888 | + android:layout_alignParentLeft="true" |
889 | + android:layout_centerHorizontal="true" |
890 | + android:layout_margin="2dp" |
891 | + android:text="System-data:" |
892 | + android:textAppearance="?android:attr/textAppearanceMedium" |
893 | + android:textColor="@color/text" |
894 | + android:textStyle="bold" |
895 | + u1f:customFont="Ubuntu-R.ttf" /> |
896 | + |
897 | + <com.canonical.ubuntu.widget.UbuntuTextView |
898 | + android:id="@+id/system_data_size" |
899 | + android:layout_width="wrap_content" |
900 | + android:layout_height="wrap_content" |
901 | + android:layout_margin="2dp" |
902 | + android:layout_toRightOf="@id/system_data_label" |
903 | + android:singleLine="true" |
904 | + android:text="used MB" |
905 | + android:textAppearance="?android:attr/textAppearanceMedium" |
906 | + android:textColor="@color/text" |
907 | + u1f:customFont="Ubuntu-R.ttf" /> |
908 | + </RelativeLayout> |
909 | + |
910 | + <RelativeLayout |
911 | + android:layout_width="wrap_content" |
912 | + android:layout_height="wrap_content" |
913 | + android:layout_marginLeft="10dp" > |
914 | + |
915 | + <com.canonical.ubuntu.widget.UbuntuTextView |
916 | + android:id="@+id/user_data_label" |
917 | + android:layout_width="wrap_content" |
918 | + android:layout_height="wrap_content" |
919 | + android:layout_alignParentLeft="true" |
920 | + android:layout_centerHorizontal="true" |
921 | + android:layout_margin="2dp" |
922 | + android:text="User-data:" |
923 | + android:textAppearance="?android:attr/textAppearanceMedium" |
924 | + android:textColor="@color/text" |
925 | + android:textStyle="bold" |
926 | + u1f:customFont="Ubuntu-R.ttf" /> |
927 | + |
928 | + <com.canonical.ubuntu.widget.UbuntuTextView |
929 | + android:id="@+id/user_datasize" |
930 | + android:layout_width="wrap_content" |
931 | + android:layout_height="wrap_content" |
932 | + android:layout_margin="2dp" |
933 | + android:layout_toRightOf="@id/user_data_label" |
934 | + android:singleLine="true" |
935 | + android:text="used MB" |
936 | android:textAppearance="?android:attr/textAppearanceMedium" |
937 | android:textColor="@color/text" |
938 | u1f:customFont="Ubuntu-R.ttf" /> |
939 | </RelativeLayout> |
940 | </LinearLayout> |
941 | |
942 | + <com.canonical.ubuntu.widget.UbuntuButton |
943 | + android:id="@+id/upgrade" |
944 | + style="@style/Button.Grey" |
945 | + android:layout_width="match_parent" |
946 | + android:layout_height="wrap_content" |
947 | + android:layout_centerHorizontal="true" |
948 | + android:layout_marginBottom="14dp" |
949 | + android:layout_above="@+id/reboot" |
950 | + android:adjustViewBounds="true" |
951 | + android:text="Install Upgrade" |
952 | + android:textColor="@color/text" |
953 | + u1f:customFont="Ubuntu-R.ttf" /> |
954 | + |
955 | + <com.canonical.ubuntu.widget.UbuntuButton |
956 | + android:id="@+id/reboot" |
957 | + style="@style/Button.Grey" |
958 | + android:layout_width="match_parent" |
959 | + android:layout_height="wrap_content" |
960 | + android:layout_alignParentBottom="true" |
961 | + android:layout_centerHorizontal="true" |
962 | + android:layout_marginBottom="14dp" |
963 | + android:adjustViewBounds="true" |
964 | + android:text="Boot Ubuntu" |
965 | + android:textColor="@color/text" |
966 | + u1f:customFont="Ubuntu-R.ttf" /> |
967 | + |
968 | </RelativeLayout> |
969 | \ No newline at end of file |
970 | |
971 | === modified file 'res/menu/installer_menu.xml' |
972 | --- res/menu/installer_menu.xml 2013-12-25 03:13:44 +0000 |
973 | +++ res/menu/installer_menu.xml 2014-06-09 11:59:50 +0000 |
974 | @@ -1,19 +1,15 @@ |
975 | <menu xmlns:android="http://schemas.android.com/apk/res/android" > |
976 | |
977 | <item |
978 | - android:id="@+id/action_delete_download" |
979 | + android:id="@+id/menu_action_delete_download" |
980 | android:orderInCategory="100" |
981 | - android:showAsAction="never" |
982 | + android:showAsAction="ifRoom" |
983 | + android:icon="@drawable/ic_action_discard" |
984 | android:title="@string/action_detele_download"/> |
985 | <item |
986 | - android:id="@+id/action_dump_terminal" |
987 | + android:id="@+id/menu_action_dump_terminal" |
988 | android:orderInCategory="100" |
989 | - android:showAsAction="never" |
990 | + android:showAsAction="ifRoom" |
991 | + android:icon="@drawable/ic_action_share" |
992 | android:title="@string/action_dump_terminal"/> |
993 | -<!-- <item |
994 | - android:id="@+id/action_settings" |
995 | - android:orderInCategory="100" |
996 | - android:showAsAction="never" |
997 | - android:title="@string/action_settings"/> |
998 | - --> |
999 | </menu> |
1000 | |
1001 | === modified file 'res/menu/launcher_menu.xml' |
1002 | --- res/menu/launcher_menu.xml 2013-12-20 03:39:53 +0000 |
1003 | +++ res/menu/launcher_menu.xml 2014-06-09 11:59:50 +0000 |
1004 | @@ -1,20 +1,29 @@ |
1005 | <menu xmlns:android="http://schemas.android.com/apk/res/android" > |
1006 | - |
1007 | - <item |
1008 | - android:id="@+id/action_uninstall" |
1009 | + <item |
1010 | + android:id="@+id/menu_action_update_android" |
1011 | + android:orderInCategory="100" |
1012 | + android:showAsAction="never" |
1013 | + android:title="@string/android_update_menu_option"/> |
1014 | + <item |
1015 | + android:id="@+id/menu_action_uninstall" |
1016 | android:orderInCategory="100" |
1017 | android:showAsAction="never" |
1018 | android:title="@string/action_uninstall"/> |
1019 | <item |
1020 | - android:id="@+id/action_del_user_data" |
1021 | + android:id="@+id/menu_action_del_user_data" |
1022 | android:orderInCategory="100" |
1023 | - android:showAsAction="never" |
1024 | + android:showAsAction="ifRoom" |
1025 | + android:icon="@drawable/ic_action_discard" |
1026 | android:title="@string/action_delete_user_data"/> |
1027 | - |
1028 | -<!-- <item |
1029 | - android:id="@+id/action_settings" |
1030 | + <item |
1031 | + android:id="@+id/menu_action_update_storage_use" |
1032 | android:orderInCategory="100" |
1033 | android:showAsAction="never" |
1034 | - android:title="@string/action_settings"/> |
1035 | ---> |
1036 | + android:title="@string/action_update_storage_use"/> |
1037 | + <item |
1038 | + android:id="@+id/menu_action_check_for_update" |
1039 | + android:orderInCategory="100" |
1040 | + android:showAsAction="ifRoom" |
1041 | + android:icon="@drawable/ic_action_refresh" |
1042 | + android:title="@string/action_check_for_update"/> |
1043 | </menu> |
1044 | |
1045 | === modified file 'res/values/attrs.xml' |
1046 | --- res/values/attrs.xml 2013-12-10 14:26:08 +0000 |
1047 | +++ res/values/attrs.xml 2014-06-09 11:59:50 +0000 |
1048 | @@ -1,20 +1,20 @@ |
1049 | <?xml version="1.0" encoding="utf-8"?> |
1050 | <!-- |
1051 | /* |
1052 | - * This file is part of Ubuntu for Android. |
1053 | + * This file is part of Ubuntu dualboot installer for Android. |
1054 | * Copyright 2013 Canonical Ltd. |
1055 | * |
1056 | - * Ubuntu for Android is free software: you can redistribute it and/or modify |
1057 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
1058 | * it under the terms of the GNU General Public License as published by |
1059 | * the Free Software Foundation. |
1060 | * |
1061 | - * Ubuntu for Android is distributed in the hope that it will be useful, |
1062 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
1063 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1064 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
1065 | * See the GNU General Public License for more details. |
1066 | * |
1067 | * You should have received a copy of the GNU General Public License |
1068 | - * along with Ubuntu for Android. If not, see <http://www.gnu.org/licenses/>. |
1069 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
1070 | */ |
1071 | --> |
1072 | |
1073 | |
1074 | === modified file 'res/values/colors.xml' |
1075 | --- res/values/colors.xml 2013-12-10 14:26:08 +0000 |
1076 | +++ res/values/colors.xml 2014-06-09 11:59:50 +0000 |
1077 | @@ -1,20 +1,20 @@ |
1078 | <?xml version="1.0" encoding="utf-8"?> |
1079 | <!-- |
1080 | /* |
1081 | - * This file is part of Ubuntu for Android. |
1082 | + * This file is part of Ubuntu dualboot installer for Android. |
1083 | * Copyright 2013 Canonical Ltd. |
1084 | * |
1085 | - * Ubuntu for Android is free software: you can redistribute it and/or modify |
1086 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
1087 | * it under the terms of the GNU General Public License as published by |
1088 | * the Free Software Foundation. |
1089 | * |
1090 | - * Ubuntu for Android is distributed in the hope that it will be useful, |
1091 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
1092 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1093 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
1094 | * See the GNU General Public License for more details. |
1095 | * |
1096 | * You should have received a copy of the GNU General Public License |
1097 | - * along with Ubuntu for Android. If not, see <http://www.gnu.org/licenses/>. |
1098 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
1099 | */ |
1100 | --> |
1101 | |
1102 | |
1103 | === added file 'res/values/ids.xml' |
1104 | --- res/values/ids.xml 1970-01-01 00:00:00 +0000 |
1105 | +++ res/values/ids.xml 2014-06-09 11:59:50 +0000 |
1106 | @@ -0,0 +1,26 @@ |
1107 | +<?xml version="1.0" encoding="utf-8"?> |
1108 | +<!-- |
1109 | +/* |
1110 | + * This file is part of Ubuntu dualboot installer for Android. |
1111 | + * Copyright 2013 Canonical Ltd. |
1112 | + * |
1113 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
1114 | + * it under the terms of the GNU General Public License as published by |
1115 | + * the Free Software Foundation. |
1116 | + * |
1117 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
1118 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1119 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
1120 | + * See the GNU General Public License for more details. |
1121 | + * |
1122 | + * You should have received a copy of the GNU General Public License |
1123 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
1124 | + */ |
1125 | +--> |
1126 | + |
1127 | +<resources> |
1128 | + <item type="id" name="ubuntu_notification" /> |
1129 | + <item type="id" name="ubuntu_progress_notification" /> |
1130 | + <item type="id" name="ubuntu_update_notification" /> |
1131 | + <item type="id" name="android_update_notification" /> |
1132 | +</resources> |
1133 | \ No newline at end of file |
1134 | |
1135 | === modified file 'res/values/strings.xml' |
1136 | --- res/values/strings.xml 2014-01-09 08:54:46 +0000 |
1137 | +++ res/values/strings.xml 2014-06-09 11:59:50 +0000 |
1138 | @@ -1,4 +1,23 @@ |
1139 | <?xml version="1.0" encoding="utf-8"?> |
1140 | +<!-- |
1141 | +/* |
1142 | + * This file is part of Ubuntu dualboot installer for Android. |
1143 | + * Copyright 2013 Canonical Ltd. |
1144 | + * |
1145 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
1146 | + * it under the terms of the GNU General Public License as published by |
1147 | + * the Free Software Foundation. |
1148 | + * |
1149 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
1150 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1151 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
1152 | + * See the GNU General Public License for more details. |
1153 | + * |
1154 | + * You should have received a copy of the GNU General Public License |
1155 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
1156 | + */ |
1157 | +--> |
1158 | + |
1159 | <resources> |
1160 | <string name="yes">Yes</string> |
1161 | <string name="no">No</string> |
1162 | @@ -11,50 +30,87 @@ |
1163 | <string name="action_dump_terminal">Dump Terminal</string> |
1164 | <string name="action_install">Install</string> |
1165 | <string name="action_uninstall">Uninstall Ubuntu</string> |
1166 | + |
1167 | <string name="action_uninstall_button">Uninstall</string> |
1168 | - <string name="action_delete_user_data">Delete Ubuntu user data</string> |
1169 | + <string name="action_uninstall_ubuntu">Uninstall Ubuntu</string> |
1170 | + <string name="action_delete_user_data">Delete Ubuntu data</string> |
1171 | + <string name="action_update_storage_use">Update storage use</string> |
1172 | + <string name="action_check_for_update">Check for update</string> |
1173 | <string name="action_delete_udata_button">Delete</string> |
1174 | <string name="cancel">Cancel</string> |
1175 | - <string name="welcome_world">Your life is about to change, welcome in Ubuntu installer</string> |
1176 | - <string name="install_button_label_install">Choose channel to install</string> |
1177 | + <string name="welcome_world">Your life is about to change, welcome to the Ubuntu installer</string> |
1178 | + <string name="install_button_label_install">Choose which channel to install</string> |
1179 | <string name="install_button_label_fetching"><![CDATA[Install Ubuntu<br/><small>fetching channel list</small>]]></string> |
1180 | <string name="install_button_label_no_channel"><![CDATA[Install Ubuntu<br/><small>no available channels</small>]]></string> |
1181 | <string name="install_button_label_resume">Resume install</string> |
1182 | - <string name="install_button_label_cancel_download">Cancel download</string> |
1183 | - <string name="install_button_label_cancel_install">Cancel install</string> |
1184 | - <string name="channel_picker_dialog_title">Select channel to install</string> |
1185 | - <string name="version_picker_dialog_title">Select version to install</string> |
1186 | + <string name="install_button_label_resume_download">Resume download</string> |
1187 | + <string name="install_button_label_pause_download">Pause download</string> |
1188 | + <string name="install_button_label_installing">Installing....</string> |
1189 | + <string name="channel_picker_dialog_title">Select which channel to install</string> |
1190 | + <string name="version_picker_dialog_title">Select which version to install</string> |
1191 | <string name="bootstrap_check">bootstrap</string> |
1192 | <string name="latest_check">latest version</string> |
1193 | <string name="downloading_release">Downloading Ubuntu</string> |
1194 | - <string name="downloading_index">Downloading images data</string> |
1195 | + <string name="downloading_index">Downloading image data</string> |
1196 | <string name="downloading_starting">Starting download</string> |
1197 | <string name="installing_release">Installing Ubuntu</string> |
1198 | <string name="uninstall_dialog_title">Uninstall Ubuntu?</string> |
1199 | + <string name="uninstall_dialog_description">Ubuntu installation will be removed and resources freed. If not specified Ubuntu user data will not be deleted</string> |
1200 | <string name="uninstalling_ubuntu">Uninstalling Ubuntu</string> |
1201 | <string name="deleting_user_data">Deleting Ubuntu user data</string> |
1202 | + <string name="deleting_download">Deleting download</string> |
1203 | <string name="fail_fetching_versions">Fail to fetch available versions</string> |
1204 | - <string name="uninstall_dialog_message">This will remove all Ubuntu system files and Ubuntu swap file</string> |
1205 | - <string name="terminal_is_empty">Terminal is emtpy.</string> |
1206 | - <string name="terminal_dump_succ">Dump Terminal successfully to file on sdcard</string> |
1207 | - <string name="terminal_dump_fail">Dump Terminal failed to file on sdcard</string> |
1208 | + <string name="uninstall_dialog_message">This will remove all Ubuntu system files and the Ubuntu swap file</string> |
1209 | + <string name="terminal_is_empty">Terminal is empty.</string> |
1210 | + <string name="terminal_dump_succ">Dump Terminal to file on sdcard successful</string> |
1211 | + <string name="terminal_dump_fail">Dump Terminal to file on sdcard failed</string> |
1212 | <string name="external_storage_unavailable">External Storage is not available</string> |
1213 | |
1214 | <string name="not_supported_title">Not supported</string> |
1215 | - <string name="not_supported_message_fmt">It appears that your device (%s) is not on the supported list of Ubuntu for Phone dual boot installer. Visit <a href="https://wiki.ubuntu.com/Touch/DualBootInstallation">https://wiki.ubuntu.com/Touch/DualBootInstallation</a> to see phones that is supported.</string> |
1216 | + <string name="not_supported_message_fmt">It appears that your device (%s) is not supported by the Ubuntu for Phone dual boot installer. Visit <a href="https://wiki.ubuntu.com/Touch/DualBootInstallation">https://wiki.ubuntu.com/Touch/DualBootInstallation</a> to see which phones are supported.</string> |
1217 | |
1218 | <string name="no_network_dialog_title">Network not available</string> |
1219 | <string name="enable_network">Enable WiFi</string> |
1220 | + <string name="not_available">Not available</string> |
1221 | + |
1222 | + <string name="android_update_dialog_title">Android system update detected</string> |
1223 | + <string name="android_update_dialog_possitive">Prepare for update</string> |
1224 | + <string name="android_update_menu_option">Prepare for Android update</string> |
1225 | + <string name="android_update_dialog_description">Android system update has been detected. Original recovery needs to be restored to complete system update. This will not afect existing Ubuntu installation. Once system is prepared start Settings application and complete system update. It is likely update removes SuperUser capability, requiring reinstall of superuser(dualboot application), existing Ubuntu installation will be preserved.</string> |
1226 | |
1227 | <!-- Strings for LaunchActivity screen --> |
1228 | <string name="launch_title">Ubuntu</string> |
1229 | <string name="label_channel">Channel:</string> |
1230 | + <string name="label_channel_target">Target channel:</string> |
1231 | <string name="label_version">Version:</string> |
1232 | <string name="label_description">Description:</string> |
1233 | + <string name="label_rootfs">rootfs:</string> |
1234 | + <string name="label_system_data">system-data:</string> |
1235 | + <string name="label_user_data">user-data:</string> |
1236 | <string name="reboot_button_label">Reboot to Ubuntu</string> |
1237 | - |
1238 | + <string name="button_install_ubuntu_update">Install Ubuntu update</string> |
1239 | + <string name="button_install_android_update">Install pending Android update</string> |
1240 | + |
1241 | + <string name="notification_title">Ubuntu</string> |
1242 | + <string name="notification_update_available">Ubuntu update available</string> |
1243 | + <string name="notification_update_installed">Ubuntu update installed</string> |
1244 | + <string name="notification_ubuntu_installed">Ubuntu installed</string> |
1245 | + <string name="notification_download_failed">Ubuntu download failed</string> |
1246 | + <string name="notification_installation_failed">Ubuntu installation failed</string> |
1247 | + <string name="notification_downloading_release">Downloading Ubuntu release</string> |
1248 | + <string name="notification_downloading_update">Downloading Ubuntu update</string> |
1249 | + <string name="notification_installing_release">Installing Ubuntu release</string> |
1250 | + <string name="notification_installing_update">Installing Ubuntu update</string> |
1251 | + <string name="notification_android_update">Android update available</string> |
1252 | + <string name="not_enough_charge_warning">Battery level is too low to continue with installation</string> |
1253 | + |
1254 | <string-array name="uninstall_options"> |
1255 | <item>Delete user data</item> |
1256 | </string-array> |
1257 | + |
1258 | + <string-array name="update_android_options"> |
1259 | + <item>Never ask again</item> |
1260 | + </string-array> |
1261 | + |
1262 | </resources> |
1263 | |
1264 | |
1265 | === modified file 'res/values/styles.xml' |
1266 | --- res/values/styles.xml 2013-12-10 14:26:08 +0000 |
1267 | +++ res/values/styles.xml 2014-06-09 11:59:50 +0000 |
1268 | @@ -1,20 +1,20 @@ |
1269 | <?xml version="1.0" encoding="utf-8"?> |
1270 | <!-- |
1271 | /* |
1272 | - * This file is part of Ubuntu for Android. |
1273 | + * This file is part of Ubuntu dualboot installer for Android. |
1274 | * Copyright 2013 Canonical Ltd. |
1275 | * |
1276 | - * Ubuntu for Android is free software: you can redistribute it and/or modify |
1277 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
1278 | * it under the terms of the GNU General Public License as published by |
1279 | * the Free Software Foundation. |
1280 | * |
1281 | - * Ubuntu for Android is distributed in the hope that it will be useful, |
1282 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
1283 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1284 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
1285 | * See the GNU General Public License for more details. |
1286 | * |
1287 | * You should have received a copy of the GNU General Public License |
1288 | - * along with Ubuntu for Android. If not, see <http://www.gnu.org/licenses/>. |
1289 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
1290 | */ |
1291 | --> |
1292 | |
1293 | |
1294 | === added file 'src/com/canonical/ubuntu/installer/BaseActivity.java' |
1295 | --- src/com/canonical/ubuntu/installer/BaseActivity.java 1970-01-01 00:00:00 +0000 |
1296 | +++ src/com/canonical/ubuntu/installer/BaseActivity.java 2014-06-09 11:59:50 +0000 |
1297 | @@ -0,0 +1,70 @@ |
1298 | +/* |
1299 | + * This file is part of Ubuntu dualboot installer for Android. |
1300 | + * Copyright 2013 Canonical Ltd. |
1301 | + * |
1302 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
1303 | + * it under the terms of the GNU General Public License as published by |
1304 | + * the Free Software Foundation. |
1305 | + * |
1306 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
1307 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1308 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
1309 | + * See the GNU General Public License for more details. |
1310 | + * |
1311 | + * You should have received a copy of the GNU General Public License |
1312 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
1313 | + */ |
1314 | + |
1315 | +package com.canonical.ubuntu.installer; |
1316 | + |
1317 | +import android.app.Activity; |
1318 | +import android.content.ComponentName; |
1319 | +import android.content.Context; |
1320 | +import android.content.Intent; |
1321 | +import android.content.ServiceConnection; |
1322 | +import android.os.IBinder; |
1323 | + |
1324 | +public class BaseActivity extends Activity { |
1325 | + public UbuntuInstallService mInstallerService; |
1326 | + private boolean mServiceIsBound; |
1327 | + |
1328 | + public BaseActivity() { |
1329 | + } |
1330 | + |
1331 | + private ServiceConnection mConnection = new ServiceConnection() { |
1332 | + public void onServiceConnected(ComponentName className, IBinder service) { |
1333 | + mInstallerService = ((UbuntuInstallService.LocalBinder)service).getService(); |
1334 | + onInstallerServiceConnected(); |
1335 | + } |
1336 | + |
1337 | + public void onServiceDisconnected(ComponentName className) { |
1338 | + mInstallerService = null; |
1339 | + onInstallerServiceDisconnected(); |
1340 | + } |
1341 | + }; |
1342 | + |
1343 | + void doBindService() { |
1344 | + bindService(new Intent(this, UbuntuInstallService.class), mConnection, Context.BIND_AUTO_CREATE); |
1345 | + mServiceIsBound = true; |
1346 | + } |
1347 | + |
1348 | + void doUnbindService() { |
1349 | + if (mServiceIsBound) { |
1350 | + // Detach our existing connection. |
1351 | + unbindService(mConnection); |
1352 | + mServiceIsBound = false; |
1353 | + } |
1354 | + } |
1355 | + |
1356 | + /** |
1357 | + * Overwrite this function to handle service connected |
1358 | + */ |
1359 | + protected void onInstallerServiceConnected() { |
1360 | + } |
1361 | + |
1362 | + /** |
1363 | + * Overwrite this function to handle service disconnected |
1364 | + */ |
1365 | + protected void onInstallerServiceDisconnected() { |
1366 | + } |
1367 | +} |
1368 | |
1369 | === added file 'src/com/canonical/ubuntu/installer/BootReceiver.java' |
1370 | --- src/com/canonical/ubuntu/installer/BootReceiver.java 1970-01-01 00:00:00 +0000 |
1371 | +++ src/com/canonical/ubuntu/installer/BootReceiver.java 2014-06-09 11:59:50 +0000 |
1372 | @@ -0,0 +1,39 @@ |
1373 | +/* |
1374 | + * This file is part of Ubuntu dualboot installer for Android. |
1375 | + * Copyright 2013 Canonical Ltd. |
1376 | + * |
1377 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
1378 | + * it under the terms of the GNU General Public License as published by |
1379 | + * the Free Software Foundation. |
1380 | + * |
1381 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
1382 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1383 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
1384 | + * See the GNU General Public License for more details. |
1385 | + * |
1386 | + * You should have received a copy of the GNU General Public License |
1387 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
1388 | + */ |
1389 | + |
1390 | +package com.canonical.ubuntu.installer; |
1391 | + |
1392 | +import android.content.BroadcastReceiver; |
1393 | +import android.content.Context; |
1394 | +import android.content.Intent; |
1395 | +import android.content.SharedPreferences; |
1396 | +import android.util.Log; |
1397 | + |
1398 | +public class BootReceiver extends BroadcastReceiver { |
1399 | + private static final String TAG = "UbuntuBootReceiver"; |
1400 | + |
1401 | + @Override |
1402 | + public void onReceive(Context context, Intent intent) { |
1403 | + // check if there is any Ubuntu update pending |
1404 | + SharedPreferences sp = context.getSharedPreferences( UbuntuInstallService.SHARED_PREF, Context.MODE_PRIVATE); |
1405 | + if (sp.getBoolean(UbuntuInstallService.PREF_KEY_UBUNTU_INSTALLED, false)) { |
1406 | + // register alarm for periodical update checks |
1407 | + Log.d(TAG, "Setting up alarm for update checks"); |
1408 | + Utils.registerUpdateCheckAlarm(context, sp); |
1409 | + } |
1410 | + } |
1411 | +} |
1412 | |
1413 | === modified file 'src/com/canonical/ubuntu/installer/InstallActivity.java' |
1414 | --- src/com/canonical/ubuntu/installer/InstallActivity.java 2014-01-09 08:54:46 +0000 |
1415 | +++ src/com/canonical/ubuntu/installer/InstallActivity.java 2014-06-09 11:59:50 +0000 |
1416 | @@ -1,3 +1,20 @@ |
1417 | +/* |
1418 | + * This file is part of Ubuntu dualboot installer for Android. |
1419 | + * Copyright 2013 Canonical Ltd. |
1420 | + * |
1421 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
1422 | + * it under the terms of the GNU General Public License as published by |
1423 | + * the Free Software Foundation. |
1424 | + * |
1425 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
1426 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1427 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
1428 | + * See the GNU General Public License for more details. |
1429 | + * |
1430 | + * You should have received a copy of the GNU General Public License |
1431 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
1432 | + */ |
1433 | + |
1434 | package com.canonical.ubuntu.installer; |
1435 | |
1436 | import java.io.File; |
1437 | @@ -13,7 +30,7 @@ |
1438 | import com.canonical.ubuntu.installer.UbuntuInstallService; |
1439 | import com.canonical.ubuntu.installer.JsonChannelParser.Image; |
1440 | import com.canonical.ubuntu.installer.UbuntuInstallService.InstallerState; |
1441 | -import com.canonical.ubuntu.installer.VersionInfo.ReleaseType; |
1442 | +import com.canonical.ubuntu.installer.UbuntuInstallService.ReleaseType; |
1443 | import com.canonical.ubuntu.widget.UbuntuButton; |
1444 | |
1445 | import android.net.ConnectivityManager; |
1446 | @@ -22,7 +39,6 @@ |
1447 | import android.os.Build; |
1448 | import android.os.Bundle; |
1449 | import android.os.Environment; |
1450 | -import android.app.Activity; |
1451 | import android.app.AlertDialog; |
1452 | import android.app.Dialog; |
1453 | import android.app.DialogFragment; |
1454 | @@ -44,36 +60,53 @@ |
1455 | import android.view.MenuItem; |
1456 | import android.view.View; |
1457 | import android.view.View.OnClickListener; |
1458 | +import android.view.ViewTreeObserver; |
1459 | import android.widget.ProgressBar; |
1460 | import android.widget.TextView; |
1461 | |
1462 | -public class InstallActivity extends Activity { |
1463 | +public class InstallActivity extends BaseActivity { |
1464 | private static final String TAG = "UbuntuInstaller"; |
1465 | |
1466 | private UbuntuButton mInstallButton; |
1467 | - private boolean mObserversRegistered; |
1468 | - |
1469 | - private InstallerState mStatus = InstallerState.READY; |
1470 | - private VersionInfo mDownloadedVersion = null; |
1471 | - |
1472 | private ProgressBar mProgressBar; |
1473 | - private TextView mProgressText; |
1474 | - |
1475 | + private TextView mProgressText; |
1476 | private TextView mTerminal; |
1477 | - private HashMap<String, String> mAvailableChannels = new HashMap<String, String>(); |
1478 | + private ViewTreeObserver.OnGlobalLayoutListener mTerminalLayoutObserver; |
1479 | + |
1480 | + private String mServerUrl; |
1481 | + private boolean mObserversRegistered; |
1482 | + private HashMap<String, String> mAvailableChannels = null; |
1483 | + private SharedPreferences mSp; |
1484 | |
1485 | @Override |
1486 | protected void onCreate(Bundle savedInstanceState) { |
1487 | super.onCreate(savedInstanceState); |
1488 | + doBindService(); |
1489 | if (! Utils.isDeviceSupported()) { |
1490 | Log.d(TAG, "Device is not supported: " + Build.DEVICE); |
1491 | showNotCompatibleDialog(); |
1492 | } |
1493 | - |
1494 | + mSp = getSharedPreferences(UbuntuInstallService.SHARED_PREF, Context.MODE_PRIVATE); |
1495 | + // Pick default server URL |
1496 | + mServerUrl = Utils.getReleaseServerUrl(this); |
1497 | + |
1498 | // check is there is already Ubuntu installed |
1499 | - checkIfUbuntuIsInstalled(); |
1500 | if (isFinishing()) return; |
1501 | |
1502 | + Intent i = getIntent(); |
1503 | + String updateCommand = i.getStringExtra("updateCommand"); |
1504 | + if (updateCommand != null) { |
1505 | + Log.e(TAG,"Started with upadteCommand:" + updateCommand); |
1506 | + File updateCommandFile = new File(updateCommand); |
1507 | + if (updateCommandFile.exists()) { |
1508 | + mSp.edit() |
1509 | + .putString(UbuntuInstallService.PREF_KEY_UPDATE_COMMAND, updateCommand) |
1510 | + .putInt(UbuntuInstallService.PREF_KEY_DOWNLOAD_TYPE, UbuntuInstallService.ReleaseType.FULL.getValue()) |
1511 | + .commit(); |
1512 | + Utils.parseAndUpdateInstallCommand(this, updateCommandFile); |
1513 | + } |
1514 | + } |
1515 | + |
1516 | setContentView(R.layout.ubuntu_dualboot_install); |
1517 | mInstallButton = (UbuntuButton) findViewById(R.id.download); |
1518 | mProgressBar = (ProgressBar) findViewById(R.id.progress); |
1519 | @@ -82,44 +115,55 @@ |
1520 | mTerminal.setMovementMethod(new ScrollingMovementMethod()); |
1521 | mProgressBar.setEnabled(false); |
1522 | mProgressBar.setProgress(0); |
1523 | - |
1524 | - SharedPreferences pref = getSharedPreferences(UbuntuInstallService.SHARED_PREF, Context.MODE_PRIVATE); |
1525 | - pref.edit().putBoolean(UbuntuInstallService.PREF_KEY_DEVELOPER, true).commit(); |
1526 | - } |
1527 | - |
1528 | + mTerminalLayoutObserver = new ViewTreeObserver.OnGlobalLayoutListener() { |
1529 | + @Override |
1530 | + public void onGlobalLayout() { |
1531 | + // update scrolling |
1532 | + final int scrollAmount = mTerminal.getLayout().getLineTop(mTerminal.getLineCount()) - mTerminal.getHeight(); |
1533 | + mTerminal.scrollTo(0, scrollAmount); |
1534 | + |
1535 | + } |
1536 | + }; |
1537 | + mSp.edit().putBoolean(UbuntuInstallService.PREF_KEY_DEVELOPER, true).commit(); |
1538 | + } |
1539 | + @Override |
1540 | + protected void onDestroy() { |
1541 | + super.onDestroy(); |
1542 | + doUnbindService(); |
1543 | + } |
1544 | + |
1545 | @Override |
1546 | public void onResume() { |
1547 | super.onResume(); |
1548 | // check is there is already Ubuntu installed |
1549 | - checkIfUbuntuIsInstalled(); |
1550 | + checkActivityStillValid(); |
1551 | if (isFinishing()) return; |
1552 | |
1553 | - // verify if network is available for download. |
1554 | - isNetworkAvailable(); |
1555 | - |
1556 | mInstallButton.setOnClickListener(mInstallButtonListener); |
1557 | IntentFilter filter = new IntentFilter(); |
1558 | filter.addAction(UbuntuInstallService.AVAILABLE_CHANNELS); |
1559 | filter.addAction(UbuntuInstallService.DOWNLOAD_RESULT); |
1560 | filter.addAction(UbuntuInstallService.PROGRESS); |
1561 | + filter.addAction(UbuntuInstallService.PROGRESS_OUPUT); |
1562 | filter.addAction(UbuntuInstallService.INSTALL_RESULT); |
1563 | - filter.addAction(UbuntuInstallService.VERSION_UPDATE); |
1564 | - filter.addAction(UbuntuInstallService.SERVICE_STATE); |
1565 | + filter.addAction(UbuntuInstallService.SERVICE_STATE_CHANGED); |
1566 | registerReceiver(mServiceObserver, filter); |
1567 | mObserversRegistered = true; |
1568 | |
1569 | // do we know last activity |
1570 | - if (mStatus == InstallerState.DOWNLOADING || mStatus == InstallerState.INSTALLING) { |
1571 | - // request last progress / status. this will update UI accordingly |
1572 | - startService(new Intent(UbuntuInstallService.GET_PROGRESS_STATUS)); |
1573 | - } else { |
1574 | - // READY + mDownloadedVersion != null => READY_TO_INSTALL |
1575 | - mDownloadedVersion = UbuntuInstallService.getDownloadedVersion(this.getApplicationContext()); |
1576 | - if (mDownloadedVersion == null) { |
1577 | - requestChannelList(); |
1578 | + if (mInstallerService != null) { |
1579 | + InstallerState state = mInstallerService.getServiceState(); |
1580 | + if (state == InstallerState.DOWNLOADING || state == InstallerState.INSTALLING) { |
1581 | + // request last progress / status. this will update UI accordingly |
1582 | + mProgressBar.setProgress(mInstallerService.getActionProgress()); |
1583 | } |
1584 | + updateUiElements(); |
1585 | + updateOuputTextview(); |
1586 | } |
1587 | - requestServiceState(); |
1588 | + // register view tree observer for terminal |
1589 | + ViewTreeObserver vto = mTerminal.getViewTreeObserver(); |
1590 | + vto.addOnGlobalLayoutListener(mTerminalLayoutObserver); |
1591 | + |
1592 | } |
1593 | |
1594 | @Override |
1595 | @@ -131,6 +175,8 @@ |
1596 | unregisterReceiver(mServiceObserver); |
1597 | } |
1598 | mObserversRegistered = false; |
1599 | + ViewTreeObserver vto = mTerminal.getViewTreeObserver(); |
1600 | + vto.removeOnGlobalLayoutListener(mTerminalLayoutObserver); |
1601 | } |
1602 | |
1603 | @Override |
1604 | @@ -143,16 +189,12 @@ |
1605 | @Override |
1606 | public boolean onOptionsItemSelected(MenuItem item) { |
1607 | switch (item.getItemId()) { |
1608 | - case R.id.action_delete_download: |
1609 | - // also attempt to uninstall ubuntu, since there should be none anyway, keep user data |
1610 | - Intent action = new Intent(UbuntuInstallService.UNINSTALL_UBUNTU); |
1611 | - action.putExtra(UbuntuInstallService.UNINSTALL_UBUNTU_EXTRA_REMOVE_USER_DATA, false); |
1612 | + case R.id.menu_action_delete_download: |
1613 | + Intent action = new Intent(UbuntuInstallService.DELETE_DOWNLOAD); |
1614 | startService(action); |
1615 | - deleteDownload(); |
1616 | - mDownloadedVersion = null; |
1617 | - requestServiceState(); |
1618 | + Utils.showToast(this.getApplicationContext(), R.string.deleting_download); |
1619 | break; |
1620 | - case R.id.action_dump_terminal: |
1621 | + case R.id.menu_action_dump_terminal: |
1622 | CharSequence terminalText = mTerminal.getText(); |
1623 | if (terminalText.length() == 0) { |
1624 | Utils.showToast(this.getApplicationContext(), R.string.terminal_is_empty); |
1625 | @@ -200,45 +242,42 @@ |
1626 | context.startActivity(intent); |
1627 | } |
1628 | |
1629 | - private void checkIfUbuntuIsInstalled() { |
1630 | + /** |
1631 | + * Check is this activity is still valid, or we should switch to another one |
1632 | + */ |
1633 | + protected void checkActivityStillValid() { |
1634 | // check is there is Ubuntu installed or is upgradeable |
1635 | - if (UbuntuInstallService.isUbuntuInstalled(getApplicationContext())) { |
1636 | - if(!UbuntuInstallService.isUpgradeable(getApplicationContext())) { |
1637 | - Log.d(TAG, "go to launch screen, and kill Install activity"); |
1638 | - LaunchActivity.startFrom(this); |
1639 | - finish(); |
1640 | - } |
1641 | - } |
1642 | + if (mInstallerService != null |
1643 | + && mSp.getBoolean(UbuntuInstallService.PREF_KEY_UBUNTU_INSTALLED, false) |
1644 | + && mInstallerService.getServiceState() != InstallerState.INSTALLING |
1645 | + && mInstallerService.getServiceState() != InstallerState.DOWNLOADING ) { |
1646 | + Log.d(TAG, "go to launch screen, and kill Install activity"); |
1647 | + LaunchActivity.startFrom(this); |
1648 | + mAvailableChannels = null; |
1649 | + finish(); |
1650 | + } |
1651 | } |
1652 | |
1653 | private void requestChannelList() { |
1654 | - startService(new Intent(UbuntuInstallService.GET_CHANNEL_LIST)); |
1655 | - } |
1656 | - |
1657 | - private void requestServiceState() { |
1658 | - startService(new Intent(UbuntuInstallService.GET_SERVICE_STATE)); |
1659 | - } |
1660 | - |
1661 | - private void deleteDownload() { |
1662 | - Intent action = new Intent(UbuntuInstallService.CLEAN_DOWNLOAD); |
1663 | - startService(action); |
1664 | - } |
1665 | - |
1666 | + mAvailableChannels = null; |
1667 | + Intent i = new Intent(UbuntuInstallService.GET_CHANNEL_LIST); |
1668 | + i.putExtra(UbuntuInstallService.GET_CHANNEL_LIST_EXTRA_SERVER_URL, mServerUrl); |
1669 | + startService(i); |
1670 | + } |
1671 | + |
1672 | OnClickListener mInstallButtonListener = new OnClickListener() { |
1673 | @Override |
1674 | public void onClick(View v) { |
1675 | // do we need to download release, or there is already one downloaded |
1676 | // user might have missed SU request, then we have downloaded release and we just need deploy it |
1677 | - // TODO: we will need to handle also download resume |
1678 | - if (mStatus == InstallerState.DOWNLOADING) { |
1679 | - Intent startInstall = new Intent(UbuntuInstallService.CANCEL_DOWNLOAD); |
1680 | - startService(startInstall); |
1681 | - } else if (mStatus == InstallerState.INSTALLING) { |
1682 | - Intent startInstall = new Intent(UbuntuInstallService.CANCEL_INSTALL); |
1683 | - startService(startInstall); |
1684 | - } else if (UbuntuInstallService.checkifReadyToInstall(v.getContext())) { |
1685 | - startInstallationIfPossible(); |
1686 | - } else if (0 != mAvailableChannels.size()) { |
1687 | + // we need to handle also download resume |
1688 | + if (mInstallerService.getServiceState() == InstallerState.DOWNLOADING) { |
1689 | + mInstallerService.pauseDownload(); |
1690 | + } else if (UbuntuInstallService.isReadyToInstall(mSp)) { |
1691 | + UbuntuInstallService.startInstallationIfPossible(v.getContext()); |
1692 | + } else if (UbuntuInstallService.isDownloadActive(mSp)) { |
1693 | + startService(new Intent(UbuntuInstallService.RESUME_DOWNLOAD)); |
1694 | + } else if (mAvailableChannels != null && 0 != mAvailableChannels.size()) { |
1695 | // get list of aliases as array |
1696 | String channels[] = mAvailableChannels.keySet().toArray(new String[mAvailableChannels.size()]); |
1697 | // look for "trusty" as default channel |
1698 | @@ -257,32 +296,21 @@ |
1699 | true /* default latest settings*/).show(); |
1700 | } else { |
1701 | // there are no channels to pick from, this was mistake, disable button |
1702 | - requestServiceState(); |
1703 | + mAvailableChannels = null; |
1704 | + updateUiElements(); |
1705 | } |
1706 | } |
1707 | }; |
1708 | |
1709 | - private void updateInfoOnUiThread(final String text) { |
1710 | + private void updateOuputTextview() { |
1711 | this.runOnUiThread(new Runnable() { |
1712 | @Override |
1713 | public void run() { |
1714 | - // keep old text in there |
1715 | - mTerminal.setText(mTerminal.getText().toString() + "\n" + text); |
1716 | - final int scrollAmount = mTerminal.getLayout().getLineTop(mTerminal.getLineCount()) - mTerminal.getHeight(); |
1717 | - mTerminal.scrollTo(0, scrollAmount); |
1718 | + mTerminal.setText(mInstallerService.getActionOutput()); |
1719 | } |
1720 | }); |
1721 | } |
1722 | - |
1723 | - private void startInstallationIfPossible() { |
1724 | - // TODO: check if we have battery and progress to install |
1725 | - Intent startInstall = new Intent(UbuntuInstallService.INSTALL_UBUNTU); |
1726 | - startService(startInstall); |
1727 | - Utils.showToast(this, "Starting Ubuntu installation"); |
1728 | - // reset progress bar |
1729 | - mProgressBar.setProgress(0); |
1730 | - } |
1731 | - |
1732 | + |
1733 | TextPickerDialog.OnChannelPicktListener mInstallDialogListener |
1734 | = new TextPickerDialog.OnChannelPicktListener() { |
1735 | public void onChannelPicked(Context context, String channel, boolean bootstrap, boolean latest) { |
1736 | @@ -297,16 +325,16 @@ |
1737 | |
1738 | private void startDownload(final String channel, final boolean bootstrap, final int version) { |
1739 | Intent startDownload = new Intent(UbuntuInstallService.DOWNLOAD_RELEASE); |
1740 | - startDownload.putExtra(UbuntuInstallService.DOWNLOAD_RELEASE_EXTRA_CHANNEL_ALIAS, channel); |
1741 | + startDownload.putExtra(UbuntuInstallService.DOWNLOAD_RELEASE_EXTRA_SERVER_URL, |
1742 | + mServerUrl); |
1743 | startDownload.putExtra(UbuntuInstallService.DOWNLOAD_RELEASE_EXTRA_CHANNEL_URL, |
1744 | - mAvailableChannels.get(channel)); |
1745 | + mAvailableChannels.get(channel)); |
1746 | startDownload.putExtra(UbuntuInstallService.DOWNLOAD_RELEASE_EXTRA_BOOTSTRAP, bootstrap); |
1747 | if (version != -1) { |
1748 | startDownload.putExtra(UbuntuInstallService.DOWNLOAD_RELEASE_EXTRA_VERSION, version); |
1749 | } |
1750 | startDownload.putExtra(UbuntuInstallService.DOWNLOAD_RELEASE_EXTRA_TYPE, ReleaseType.FULL.getValue()); |
1751 | startService(startDownload); |
1752 | - mTerminal.setText(R.string.downloading_starting); |
1753 | mProgressBar.setProgress(0); |
1754 | } |
1755 | |
1756 | @@ -317,9 +345,11 @@ |
1757 | new Thread(new Runnable() { |
1758 | @Override |
1759 | public void run() { |
1760 | - String jsonStr = Utils.httpDownload(UbuntuInstallService.BASE_URL |
1761 | - + mAvailableChannels.get(channel)); |
1762 | - // TODO: handle malformed JSON |
1763 | + String jsonStr = Utils.httpDownload( mServerUrl + mAvailableChannels.get(channel)); |
1764 | + if (jsonStr == null) { |
1765 | + Utils.showToast(context, "Wrong url to channel list"); |
1766 | + return; |
1767 | + } |
1768 | final List<Image> releases = JsonChannelParser.getAvailableReleases(jsonStr, ReleaseType.FULL); |
1769 | |
1770 | runOnUiThread(new Runnable() { |
1771 | @@ -351,21 +381,45 @@ |
1772 | }).start(); |
1773 | } |
1774 | |
1775 | - private void updateUiElements() { |
1776 | + @Override |
1777 | + protected void onInstallerServiceConnected() { |
1778 | + updateUiElements(); |
1779 | + updateOuputTextview(); |
1780 | + } |
1781 | + |
1782 | + protected void updateUiElements() { |
1783 | + checkActivityStillValid(); |
1784 | + if (isFinishing()) return; |
1785 | this.runOnUiThread(new Runnable() { |
1786 | @Override |
1787 | - public void run() { |
1788 | - Log.v(TAG,"updateUiElements(" + mStatus + ")"); |
1789 | - switch (mStatus) { |
1790 | + public void run() { |
1791 | + InstallerState state = mInstallerService.getServiceState(); |
1792 | + Log.v(TAG,"updateUiElements(" + state + ")"); |
1793 | + // check if should fetch list of channels |
1794 | + if ( state == InstallerState.READY |
1795 | + && state != InstallerState.FETCHING_CHANNELS |
1796 | + && mAvailableChannels == null |
1797 | + && isNetworkAvailable() |
1798 | + && ! UbuntuInstallService.isDownloadActive(mSp) |
1799 | + && ! UbuntuInstallService.isReadyToInstall(mSp)) { |
1800 | + requestChannelList(); |
1801 | + } |
1802 | + switch (state) { |
1803 | case READY: |
1804 | { |
1805 | - if (mDownloadedVersion != null) { |
1806 | + if (UbuntuInstallService.isDownloadActive(mSp)) { |
1807 | + mInstallButton.setText(R.string.install_button_label_resume_download); |
1808 | + mInstallButton.setEnabled(true); |
1809 | + mProgressBar.setEnabled(false); |
1810 | + mProgressBar.setProgress(0); |
1811 | + mProgressText.setText(""); |
1812 | + } else if (UbuntuInstallService.isReadyToInstall(mSp)) { |
1813 | mInstallButton.setText(R.string.install_button_label_resume); |
1814 | mInstallButton.setEnabled(true); |
1815 | mProgressBar.setEnabled(false); |
1816 | mProgressBar.setProgress(0); |
1817 | mProgressText.setText(""); |
1818 | - } else if (mAvailableChannels.size() > 0) { |
1819 | + } else if (mAvailableChannels != null && mAvailableChannels.size() > 0) { |
1820 | mInstallButton.setText(R.string.install_button_label_install); |
1821 | mInstallButton.setEnabled(true); |
1822 | mProgressBar.setEnabled(false); |
1823 | @@ -388,18 +442,24 @@ |
1824 | mProgressText.setText(""); |
1825 | break; |
1826 | case DOWNLOADING: |
1827 | - mInstallButton.setText(R.string.install_button_label_cancel_download); |
1828 | + mInstallButton.setText(R.string.install_button_label_pause_download); |
1829 | mInstallButton.setEnabled(true); |
1830 | mProgressBar.setEnabled(true); |
1831 | mProgressText.setText(R.string.downloading_release); |
1832 | break; |
1833 | case INSTALLING: |
1834 | - mInstallButton.setText(R.string.install_button_label_cancel_install); |
1835 | - mInstallButton.setEnabled(true); |
1836 | + mInstallButton.setText(R.string.install_button_label_installing); |
1837 | + mInstallButton.setEnabled(false); |
1838 | mProgressBar.setEnabled(true); |
1839 | + mProgressBar.setProgress(mInstallerService.getActionProgress()); |
1840 | mProgressText.setText(R.string.installing_release); |
1841 | break; |
1842 | + default: |
1843 | + // ignore rest of the states |
1844 | + break; |
1845 | } |
1846 | + // dismiss notification we don't need |
1847 | + mInstallerService.dismissUbuntuNotification(); |
1848 | } |
1849 | }); |
1850 | } |
1851 | @@ -410,63 +470,40 @@ |
1852 | @Override |
1853 | public void onReceive(Context context, Intent intent) { |
1854 | String action = intent.getAction(); |
1855 | - Log.v(TAG,"mServiceObserver.onReceive(" + action + ")"); |
1856 | // List of available channels fetched |
1857 | if (action.equals(UbuntuInstallService.AVAILABLE_CHANNELS)) { |
1858 | - // ignore channel list if we have already downloaded release |
1859 | - if (!UbuntuInstallService.checkifReadyToInstall(context)) { |
1860 | - mAvailableChannels = (HashMap<String, String>) |
1861 | - intent.getSerializableExtra(UbuntuInstallService.AVAILABLE_CHANNELS_EXTRA_CHANNELS); |
1862 | - mStatus = InstallerState.READY; |
1863 | - updateUiElements(); |
1864 | - } |
1865 | + Log.v(TAG,"mServiceObserver: available channels received"); |
1866 | + mAvailableChannels = (HashMap<String, String>) |
1867 | + intent.getSerializableExtra(UbuntuInstallService.AVAILABLE_CHANNELS_EXTRA_CHANNELS); |
1868 | // Handle progress |
1869 | } else if (action.equals(UbuntuInstallService.PROGRESS)) { |
1870 | - String p = intent.getStringExtra(UbuntuInstallService.PROGRESS_EXTRA_TEXT); |
1871 | - int progress = intent.getIntExtra(UbuntuInstallService.PROGRESS_EXTRA_INT, -1); |
1872 | - if (progress != -1) { |
1873 | - mProgressBar.setProgress(progress); |
1874 | - Log.d(TAG, "Progress: " + progress); |
1875 | - } |
1876 | - if (p != null && !p.equals("")) { |
1877 | - // update terminal with progress text |
1878 | - updateInfoOnUiThread(p); |
1879 | - } |
1880 | - |
1881 | + mProgressBar.setProgress(mInstallerService.getActionProgress()); |
1882 | + } else if (action.equals(UbuntuInstallService.PROGRESS_OUPUT)) { |
1883 | + updateOuputTextview(); |
1884 | // Handle install result |
1885 | } else if(action.equals(UbuntuInstallService.INSTALL_RESULT)) { |
1886 | + Log.v(TAG,"mServiceObserver: installaction finished"); |
1887 | int r = intent.getIntExtra(UbuntuInstallService.INSTALL_RESULT_EXTRA_INT, -1); |
1888 | if (r == 0) { |
1889 | Utils.showToast(context, "Install completed"); |
1890 | mProgressBar.setProgress(100); |
1891 | - deleteDownload(); |
1892 | - // go to launch screen, and kill this activity. |
1893 | - LaunchActivity.startFrom(context); |
1894 | - finish(); |
1895 | } else { |
1896 | Utils.showToast(context, "Installation failed:"); |
1897 | String reason = intent.getStringExtra(UbuntuInstallService.INSTALL_RESULT_EXTRA_STR); |
1898 | Utils.showToast(context, reason); |
1899 | - updateInfoOnUiThread(reason); |
1900 | - // if we still have download go back to resume installation |
1901 | - // TODO: we should distinguish between resume/retry |
1902 | - mDownloadedVersion = UbuntuInstallService.getDownloadedVersion(context); |
1903 | - if (UbuntuInstallService.checkifReadyToInstall(context)) { |
1904 | - mDownloadedVersion = UbuntuInstallService.getDownloadedVersion(context); |
1905 | - } else { |
1906 | - deleteDownload(); |
1907 | - mDownloadedVersion = null; |
1908 | - requestChannelList(); |
1909 | - } |
1910 | - updateUiElements(); |
1911 | + updateOuputTextview(); |
1912 | } |
1913 | + updateUiElements(); |
1914 | |
1915 | // Handle download result |
1916 | } else if(action.equals(UbuntuInstallService.DOWNLOAD_RESULT)) { |
1917 | + Log.v(TAG,"mServiceObserver: download finished"); |
1918 | int r = intent.getIntExtra(UbuntuInstallService.DOWNLOAD_RESULT_EXTRA_INT, -1); |
1919 | if (r == 0) { |
1920 | - Utils.showToast(context, "Download completed, ready to install Ubuntu"); |
1921 | - startInstallationIfPossible(); |
1922 | + if (mInstallerService.getServiceState() == InstallerState.READY) { |
1923 | + UbuntuInstallService.startInstallationIfPossible(context); |
1924 | + mInstallerService.resetActionOutput(); |
1925 | + } |
1926 | } else { |
1927 | String reason = intent.getStringExtra(UbuntuInstallService.INSTALL_RESULT_EXTRA_STR); |
1928 | // make sure it was not cancelled by user |
1929 | @@ -474,27 +511,13 @@ |
1930 | reason = "Download failed: " + reason; |
1931 | } |
1932 | Utils.showToast(context, reason); |
1933 | - |
1934 | - // check if network is available for download. |
1935 | - // isNetworkAvailable(); |
1936 | - |
1937 | - updateInfoOnUiThread(reason); |
1938 | - requestChannelList(); |
1939 | - } |
1940 | - } else if (action.equals(UbuntuInstallService.VERSION_UPDATE)) { |
1941 | - checkIfUbuntuIsInstalled(); |
1942 | - if (!isFinishing()) { |
1943 | - // check what button should be shown |
1944 | - if (UbuntuInstallService.checkifReadyToInstall(context)) { |
1945 | - mDownloadedVersion = UbuntuInstallService.getDownloadedVersion(context); |
1946 | - } |
1947 | + updateOuputTextview(); |
1948 | updateUiElements(); |
1949 | } |
1950 | - } else if (action.equals(UbuntuInstallService.SERVICE_STATE)) { |
1951 | - checkIfUbuntuIsInstalled(); |
1952 | + } else if (action.equals(UbuntuInstallService.SERVICE_STATE_CHANGED)) { |
1953 | + Log.v(TAG,"mServiceObserver: service state changed"); |
1954 | + checkActivityStillValid(); |
1955 | if (!isFinishing()) { |
1956 | - mStatus = InstallerState.fromOrdian(intent.getIntExtra(UbuntuInstallService.SERVICE_STATE, 0)); |
1957 | - mDownloadedVersion = UbuntuInstallService.getDownloadedVersion(context); |
1958 | updateUiElements(); |
1959 | } |
1960 | } |
1961 | @@ -507,7 +530,7 @@ |
1962 | * |
1963 | * @return true if network is available |
1964 | */ |
1965 | - private boolean isNetworkAvailable () { |
1966 | + private boolean isNetworkAvailable() { |
1967 | final ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); |
1968 | final NetworkInfo activeNetwork = conMgr.getActiveNetworkInfo(); |
1969 | if (activeNetwork != null && activeNetwork.isConnected()) { |
1970 | @@ -516,11 +539,12 @@ |
1971 | |
1972 | Utils.createConfirmationDialog(this, |
1973 | R.string.no_network_dialog_title, |
1974 | + 0, |
1975 | R.string.enable_network, |
1976 | R.string.cancel, |
1977 | new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK), |
1978 | - -1, // toastText |
1979 | - -1, // choiceItemsArray |
1980 | + 0, // toastText |
1981 | + 0, // choiceItemsArray |
1982 | null, // defaultChoiceValues |
1983 | null // choiceClickListener |
1984 | ).show(); |
1985 | |
1986 | === modified file 'src/com/canonical/ubuntu/installer/JsonChannelParser.java' |
1987 | --- src/com/canonical/ubuntu/installer/JsonChannelParser.java 2013-12-16 02:11:14 +0000 |
1988 | +++ src/com/canonical/ubuntu/installer/JsonChannelParser.java 2014-06-09 11:59:50 +0000 |
1989 | @@ -1,3 +1,20 @@ |
1990 | +/* |
1991 | + * This file is part of Ubuntu dualboot installer for Android. |
1992 | + * Copyright 2013 Canonical Ltd. |
1993 | + * |
1994 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
1995 | + * it under the terms of the GNU General Public License as published by |
1996 | + * the Free Software Foundation. |
1997 | + * |
1998 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
1999 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2000 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
2001 | + * See the GNU General Public License for more details. |
2002 | + * |
2003 | + * You should have received a copy of the GNU General Public License |
2004 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
2005 | + */ |
2006 | + |
2007 | package com.canonical.ubuntu.installer; |
2008 | |
2009 | import java.util.Collections; |
2010 | @@ -5,7 +22,7 @@ |
2011 | import java.util.LinkedList; |
2012 | import java.util.List; |
2013 | |
2014 | -import com.canonical.ubuntu.installer.VersionInfo.ReleaseType; |
2015 | +import com.canonical.ubuntu.installer.UbuntuInstallService.ReleaseType; |
2016 | import com.google.gson.Gson; |
2017 | import com.google.gson.JsonArray; |
2018 | import com.google.gson.JsonObject; |
2019 | @@ -26,6 +43,7 @@ |
2020 | } |
2021 | |
2022 | public class Image { |
2023 | + Integer base; |
2024 | String description; |
2025 | Integer version; |
2026 | String type; |
2027 | @@ -41,21 +59,25 @@ |
2028 | static public List<Image> getAvailableReleases(String jsonStr, ReleaseType filter) { |
2029 | LinkedList<Image> releases = new LinkedList<Image>(); |
2030 | |
2031 | - JsonObject index = new JsonParser().parse(jsonStr).getAsJsonObject(); |
2032 | - JsonArray images = index.get("images").getAsJsonArray(); |
2033 | - int size = images.size(); |
2034 | - |
2035 | - for(int j = 0; j < size; j++) { |
2036 | - Image image = new Gson().fromJson(images.get(j), Image.class); |
2037 | - ReleaseType type = ReleaseType.UNKNOWN; |
2038 | - if (FULL_RELEASE.equals(image.type)) { |
2039 | - type = ReleaseType.FULL; |
2040 | - } else if (DELTA_RELEASE.equals(image.type)) { |
2041 | - type = ReleaseType.DELTA; |
2042 | - } |
2043 | - if (filter == type) { |
2044 | - releases.add(image); |
2045 | - } |
2046 | + try { |
2047 | + JsonObject index = new JsonParser().parse(jsonStr).getAsJsonObject(); |
2048 | + JsonArray images = index.get("images").getAsJsonArray(); |
2049 | + int size = images.size(); |
2050 | + |
2051 | + for(int j = 0; j < size; j++) { |
2052 | + Image image = new Gson().fromJson(images.get(j), Image.class); |
2053 | + ReleaseType type = ReleaseType.UNKNOWN; |
2054 | + if (FULL_RELEASE.equals(image.type)) { |
2055 | + type = ReleaseType.FULL; |
2056 | + } else if (DELTA_RELEASE.equals(image.type)) { |
2057 | + type = ReleaseType.DELTA; |
2058 | + } |
2059 | + if (filter == type) { |
2060 | + releases.add(image); |
2061 | + } |
2062 | + } |
2063 | + } catch (com.google.gson.JsonSyntaxException e) { |
2064 | + // ignore, empty list will be returned |
2065 | } |
2066 | // sort list |
2067 | Collections.sort(releases, imageComparator()); |
2068 | |
2069 | === modified file 'src/com/canonical/ubuntu/installer/LaunchActivity.java' |
2070 | --- src/com/canonical/ubuntu/installer/LaunchActivity.java 2014-01-09 08:54:46 +0000 |
2071 | +++ src/com/canonical/ubuntu/installer/LaunchActivity.java 2014-06-09 11:59:50 +0000 |
2072 | @@ -1,12 +1,30 @@ |
2073 | +/* |
2074 | + * This file is part of Ubuntu dualboot installer for Android. |
2075 | + * Copyright 2013 Canonical Ltd. |
2076 | + * |
2077 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
2078 | + * it under the terms of the GNU General Public License as published by |
2079 | + * the Free Software Foundation. |
2080 | + * |
2081 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
2082 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2083 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
2084 | + * See the GNU General Public License for more details. |
2085 | + * |
2086 | + * You should have received a copy of the GNU General Public License |
2087 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
2088 | + */ |
2089 | + |
2090 | package com.canonical.ubuntu.installer; |
2091 | |
2092 | -import android.app.Activity; |
2093 | -import android.app.AlertDialog; |
2094 | +import java.util.Locale; |
2095 | + |
2096 | import android.content.BroadcastReceiver; |
2097 | import android.content.Context; |
2098 | import android.content.DialogInterface; |
2099 | import android.content.Intent; |
2100 | import android.content.IntentFilter; |
2101 | +import android.content.SharedPreferences; |
2102 | import android.os.Bundle; |
2103 | import android.util.Log; |
2104 | import android.view.Menu; |
2105 | @@ -15,80 +33,121 @@ |
2106 | import android.view.View.OnClickListener; |
2107 | import android.widget.TextView; |
2108 | |
2109 | +import com.canonical.ubuntu.installer.UbuntuInstallService.InstallerState; |
2110 | import com.canonical.ubuntu.widget.UbuntuButton; |
2111 | |
2112 | -public class LaunchActivity extends Activity { |
2113 | +public class LaunchActivity extends BaseActivity { |
2114 | private static final String TAG = "UbuntuLaunchActivity"; |
2115 | - private UbuntuButton mRebootButton; |
2116 | + |
2117 | + private SharedPreferences mSharedPreferences; |
2118 | + private TextView mTextTitle; |
2119 | private TextView mTextChannel; |
2120 | private TextView mTextChannelLabel; |
2121 | + private TextView mTextRefChannel; |
2122 | + private TextView mTextRefChannelLabel; |
2123 | private TextView mTextVersion; |
2124 | private TextView mTextVersionLabel; |
2125 | - private TextView mTextTitle; |
2126 | private TextView mTextDescriptionLabel; |
2127 | private TextView mTextDescription; |
2128 | - private VersionInfo mUbuntuVersion; |
2129 | + private TextView mTextUseRootfs; |
2130 | + private TextView mTextUseRootfsLabel; |
2131 | + private TextView mTextUseSystemData; |
2132 | + private TextView mTextUseSystemDataLabel; |
2133 | + private TextView mTextUseUserData; |
2134 | + private TextView mTextUseUserDataLabel; |
2135 | + private UbuntuButton mRebootButton; |
2136 | + private UbuntuButton mUpdateButton; |
2137 | + private boolean mAndroidUpdatePending; |
2138 | + private Menu mMenu; |
2139 | |
2140 | @Override |
2141 | protected void onCreate(Bundle savedInstanceState) { |
2142 | super.onCreate(savedInstanceState); |
2143 | - // check if Ubuntu is installed |
2144 | - ensureUbuntuIsInstalled(); |
2145 | - if (isFinishing()) return; |
2146 | - |
2147 | + doBindService(); |
2148 | + mSharedPreferences = getSharedPreferences( UbuntuInstallService.SHARED_PREF, Context.MODE_PRIVATE); |
2149 | setContentView(R.layout.ubuntu_dualboot_launch); |
2150 | - mRebootButton = (UbuntuButton) findViewById(R.id.download); |
2151 | mTextChannel = (TextView) findViewById(R.id.channel); |
2152 | + mTextChannelLabel = (TextView) findViewById(R.id.channel_label); |
2153 | + mTextRefChannel = (TextView) findViewById(R.id.ref_channel); |
2154 | + mTextRefChannelLabel = (TextView) findViewById(R.id.ref_channel_label); |
2155 | mTextVersion = (TextView) findViewById(R.id.version); |
2156 | - mTextChannelLabel = (TextView) findViewById(R.id.channel_label); |
2157 | mTextVersionLabel = (TextView) findViewById(R.id.version_label); |
2158 | - mTextTitle = (TextView) findViewById(R.id.title); |
2159 | mTextDescriptionLabel = (TextView) findViewById(R.id.description_label); |
2160 | mTextDescription = (TextView) findViewById(R.id.description); |
2161 | + mTextUseRootfs = (TextView) findViewById(R.id.rootfssize); |
2162 | + mTextUseRootfsLabel = (TextView) findViewById(R.id.rootfs_label); |
2163 | + mTextUseSystemData = (TextView) findViewById(R.id.system_data_size); |
2164 | + mTextUseSystemDataLabel = (TextView) findViewById(R.id.system_data_label); |
2165 | + mTextUseUserData = (TextView) findViewById(R.id.user_datasize); |
2166 | + mTextUseUserDataLabel = (TextView) findViewById(R.id.user_data_label); |
2167 | + mTextTitle = (TextView) findViewById(R.id.title); |
2168 | mTextTitle.setText(R.string.launch_title); |
2169 | + mUpdateButton = (UbuntuButton) findViewById(R.id.upgrade); |
2170 | + mRebootButton = (UbuntuButton) findViewById(R.id.reboot); |
2171 | mRebootButton.setText(R.string.reboot_button_label); |
2172 | - fillInstalledVersionInfo(); |
2173 | - |
2174 | - // check the upgradeable image. |
2175 | - startService(new Intent(UbuntuInstallService.IS_UBUNTU_UPGRADABLE)); |
2176 | - } |
2177 | - |
2178 | + mUpdateButton.setText(R.string.button_install_ubuntu_update); |
2179 | + mTextVersionLabel.setText(R.string.label_version); |
2180 | + mTextChannelLabel.setText(R.string.label_channel); |
2181 | + mTextRefChannelLabel.setText(R.string.label_channel_target); |
2182 | + mTextDescriptionLabel.setText(R.string.label_description); |
2183 | + mTextUseRootfsLabel.setText(R.string.label_rootfs); |
2184 | + mTextUseSystemDataLabel.setText(R.string.label_system_data); |
2185 | + mTextUseUserDataLabel.setText(R.string.label_user_data); |
2186 | + // check for updates |
2187 | + startService(new Intent(UbuntuInstallService.CHECK_PENDING_UPDATES)); |
2188 | + } |
2189 | + |
2190 | + @Override |
2191 | + protected void onDestroy() { |
2192 | + super.onDestroy(); |
2193 | + doUnbindService(); |
2194 | + } |
2195 | + |
2196 | @Override |
2197 | public void onResume() { |
2198 | super.onResume(); |
2199 | // check is there is Ubuntu installed |
2200 | - ensureUbuntuIsInstalled(); |
2201 | + checkActivityStillValid(); |
2202 | if (isFinishing()) return; |
2203 | |
2204 | mRebootButton.setOnClickListener(mRebootButtonListener); |
2205 | + mUpdateButton.setOnClickListener(mRebootButtonListener); |
2206 | IntentFilter filter = new IntentFilter(); |
2207 | - filter.addAction(UbuntuInstallService.VERSION_UPDATE); |
2208 | + filter.addAction(UbuntuInstallService.SERVICE_STATE_CHANGED); |
2209 | + filter.addAction(UbuntuInstallService.STORAGE_USE_UPDATED); |
2210 | + filter.addAction(UbuntuInstallService.ANDROID_UPDATE_PENDING); |
2211 | + filter.addAction(UbuntuInstallService.UBUNTU_UPDATE_PENDING); |
2212 | + filter.addAction(UbuntuInstallService.UBUNTU_UPDATE_AVAILABLE); |
2213 | registerReceiver(mServiceObserver, filter); |
2214 | + updateUiElements(); |
2215 | } |
2216 | |
2217 | @Override |
2218 | public void onPause() { |
2219 | super.onPause(); |
2220 | mRebootButton.setOnClickListener(null); |
2221 | + mUpdateButton.setOnClickListener(null); |
2222 | // cancel observer if there is any |
2223 | unregisterReceiver(mServiceObserver); |
2224 | } |
2225 | |
2226 | @Override |
2227 | public boolean onCreateOptionsMenu(Menu menu) { |
2228 | - // Inflate the menu; this adds items to the action bar if it is present. |
2229 | getMenuInflater().inflate(R.menu.launcher_menu, menu); |
2230 | + menu.findItem(R.id.menu_action_update_android).setShowAsAction( MenuItem.SHOW_AS_ACTION_NEVER); |
2231 | + mMenu = menu; |
2232 | return true; |
2233 | } |
2234 | |
2235 | @Override |
2236 | public boolean onOptionsItemSelected(MenuItem item) { |
2237 | switch (item.getItemId()) { |
2238 | - case R.id.action_uninstall: |
2239 | + case R.id.menu_action_uninstall: |
2240 | // show dialog |
2241 | final Intent uninstall = new Intent(UbuntuInstallService.UNINSTALL_UBUNTU); |
2242 | Utils.createConfirmationDialog(this, |
2243 | R.string.uninstall_dialog_title, |
2244 | + R.string.uninstall_dialog_description, |
2245 | R.string.action_uninstall_button, |
2246 | R.string.cancel, |
2247 | uninstall, |
2248 | @@ -103,71 +162,176 @@ |
2249 | } |
2250 | }).show(); |
2251 | break; |
2252 | - case R.id.action_del_user_data: |
2253 | - Intent action = new Intent(UbuntuInstallService.DELETE_UBUNTU_USER_DATA); |
2254 | + case R.id.menu_action_del_user_data: |
2255 | + final Intent action = new Intent(UbuntuInstallService.DELETE_UBUNTU_USER_DATA); |
2256 | Utils.createConfirmationDialog(this, |
2257 | R.string.action_delete_user_data, |
2258 | + 0, |
2259 | R.string.action_delete_udata_button, |
2260 | R.string.cancel, |
2261 | action, |
2262 | R.string.deleting_user_data, |
2263 | - -1, |
2264 | + 0, // choiceItemsArray |
2265 | null, |
2266 | null).show(); |
2267 | break; |
2268 | + case R.id.menu_action_update_storage_use: |
2269 | + final Intent updateStorage = new Intent(UbuntuInstallService.UPDATE_STORAGE_USE); |
2270 | + startService(updateStorage); |
2271 | + break; |
2272 | + case R.id.menu_action_check_for_update: |
2273 | + final Intent checkForUpdate = new Intent(UbuntuInstallService.CHECK_IF_UPDATE_AVAILABLE); |
2274 | + startService(checkForUpdate); |
2275 | + break; |
2276 | + case R.id.menu_action_update_android: |
2277 | + showAndroidUpdateDialog(); |
2278 | + break; |
2279 | } |
2280 | return super.onOptionsItemSelected(item); |
2281 | } |
2282 | |
2283 | + public void showAndroidUpdateDialog() { |
2284 | + final Intent update = new Intent(UbuntuInstallService.PREPARE_ANDROID_UPDATE); |
2285 | + Utils.createAndroidUpdateConfirmationDialog(this, |
2286 | + R.string.android_update_dialog_title, |
2287 | + R.string.android_update_dialog_description, |
2288 | + R.string.android_update_dialog_possitive, |
2289 | + R.string.cancel, |
2290 | + update, |
2291 | + 0, |
2292 | + R.array.update_android_options, |
2293 | + new boolean[]{mSharedPreferences.getBoolean(UbuntuInstallService.PREF_KEY_ANDROID_UPDATE_DISMISSED, false)}, |
2294 | + new DialogInterface.OnMultiChoiceClickListener() { |
2295 | + @Override |
2296 | + public void onClick(DialogInterface dialog, int which, boolean isChecked) { |
2297 | + // update data in the shared preferences |
2298 | + mSharedPreferences.edit() |
2299 | + .putBoolean(UbuntuInstallService.PREF_KEY_ANDROID_UPDATE_DISMISSED, isChecked) |
2300 | + .commit(); |
2301 | + mAndroidUpdatePending = !isChecked; |
2302 | + } |
2303 | + }).show(); |
2304 | + } |
2305 | + |
2306 | public static void startFrom(Context context) { |
2307 | Intent intent = new Intent(context, LaunchActivity.class); |
2308 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); |
2309 | context.startActivity(intent); |
2310 | } |
2311 | |
2312 | - private void fillInstalledVersionInfo() { |
2313 | - mTextChannel.setText(mUbuntuVersion.getChannelAlias()); |
2314 | - mTextVersion.setText(Integer.toString(mUbuntuVersion.getVersion())); |
2315 | - mTextDescription.setText(mUbuntuVersion.getDescription()); |
2316 | - mTextChannelLabel.setText(R.string.label_channel); |
2317 | - mTextVersionLabel.setText(R.string.label_version); |
2318 | - mTextDescriptionLabel.setText(R.string.label_description); |
2319 | - } |
2320 | - |
2321 | + @Override |
2322 | + protected void onInstallerServiceConnected() { |
2323 | + updateUiElements(); |
2324 | + } |
2325 | + |
2326 | + protected void updateUiElements() { |
2327 | + checkActivityStillValid(); |
2328 | + if (isFinishing()) return; |
2329 | + this.runOnUiThread(new Runnable() { |
2330 | + @Override |
2331 | + public void run() { |
2332 | + String defValue = getString(R.string.not_available); |
2333 | + mTextChannel.setText(mSharedPreferences.getString(UbuntuInstallService.PREF_KEY_VERSION_CHANNEL, defValue)); |
2334 | + mTextRefChannel.setText(mSharedPreferences.getString(UbuntuInstallService.PREF_KEY_VERSION_CHANNEL_TARGET, defValue)); |
2335 | + mTextVersion.setText(mSharedPreferences.getString(UbuntuInstallService.PREF_KEY_VERSION_NUMBER, defValue)); |
2336 | + mTextDescription.setText(mSharedPreferences.getString(UbuntuInstallService.PREF_KEY_VERSION_DESCRIPTION, defValue)); |
2337 | + mTextUseRootfs.setText(formatSize(mSharedPreferences.getInt(UbuntuInstallService.PREF_KEY_SIZE_ROOTFS, -1))); |
2338 | + mTextUseSystemData.setText(formatSize(mSharedPreferences.getInt(UbuntuInstallService.PREF_KEY_SIZE_SYSTEM_DATA, -1))); |
2339 | + mTextUseUserData.setText(formatSize(mSharedPreferences.getInt(UbuntuInstallService.PREF_KEY_SIZE_USER_DATA, -1))); |
2340 | + if (mSharedPreferences.getBoolean(UbuntuInstallService.PREF_KEY_PENDING_UPDATE, false)) { |
2341 | + mUpdateButton.setVisibility(View.VISIBLE); |
2342 | + } else { |
2343 | + mUpdateButton.setVisibility(View.GONE); |
2344 | + } |
2345 | + // dismiss notification we don't need |
2346 | + if (mInstallerService != null) { |
2347 | + mInstallerService.dismissUbuntuNotification(); |
2348 | + mInstallerService.dismissUbuntuUpdateNotification(); |
2349 | + mInstallerService.dismissAndroidNotification(); |
2350 | + } |
2351 | + if (mAndroidUpdatePending) { |
2352 | + showAndroidUpdateDialog(); |
2353 | + } |
2354 | + } |
2355 | + }); |
2356 | + } |
2357 | + |
2358 | + String formatSize(int size) { |
2359 | + if (size != -1) { |
2360 | + return String.format(Locale.US,"%d MB", size); |
2361 | + } else { |
2362 | + return getString(R.string.not_available); |
2363 | + } |
2364 | + } |
2365 | + |
2366 | /** |
2367 | - * Get installed version to check Ubuntu is installed |
2368 | + * Check is this activity is still valid, or we should switch to another one |
2369 | */ |
2370 | - private void ensureUbuntuIsInstalled() { |
2371 | - VersionInfo v = UbuntuInstallService.getInstalledVersion(this.getApplicationContext()); |
2372 | - if (v == null) { |
2373 | + private void checkActivityStillValid() { |
2374 | + |
2375 | + if (! mSharedPreferences.getBoolean(UbuntuInstallService.PREF_KEY_UBUNTU_INSTALLED, false) |
2376 | + || (mInstallerService != null |
2377 | + && (mInstallerService.getServiceState() == InstallerState.INSTALLING |
2378 | + || mInstallerService.getServiceState() == InstallerState.DOWNLOADING) |
2379 | + ) |
2380 | + ) { |
2381 | // go back to install screen, and release myself. |
2382 | InstallActivity.startFrom(this); |
2383 | finish(); |
2384 | - } else { |
2385 | - mUbuntuVersion = v; |
2386 | } |
2387 | } |
2388 | |
2389 | OnClickListener mRebootButtonListener = new OnClickListener() { |
2390 | @Override |
2391 | public void onClick(View v) { |
2392 | - startService(new Intent(UbuntuInstallService.REBOOT_UBUNTU)); |
2393 | + if (v.getId() == R.id.reboot) { |
2394 | + startService(new Intent(UbuntuInstallService.REBOOT_UBUNTU)); |
2395 | + } else if (v.getId() == R.id.upgrade) { |
2396 | + if (UbuntuInstallService.isReadyToInstall(mSharedPreferences)) { |
2397 | + UbuntuInstallService.startInstallationIfPossible(v.getContext()); |
2398 | + } else if (UbuntuInstallService.isDownloadActive(mSharedPreferences)) { |
2399 | + startService(new Intent(UbuntuInstallService.RESUME_DOWNLOAD)); |
2400 | + } else { |
2401 | + startService(new Intent(UbuntuInstallService.DOWNLOAD_UPDATE)); |
2402 | + } |
2403 | + } |
2404 | } |
2405 | }; |
2406 | |
2407 | BroadcastReceiver mServiceObserver = new BroadcastReceiver() { |
2408 | - @SuppressWarnings("unchecked") |
2409 | @Override |
2410 | - public void onReceive(Context context, Intent intent) { |
2411 | - String action = intent.getAction(); |
2412 | - if (action.equals(UbuntuInstallService.VERSION_UPDATE)) { |
2413 | - ensureUbuntuIsInstalled(); |
2414 | - if(UbuntuInstallService.isUpgradeable(getApplicationContext())) { |
2415 | - Log.d(TAG, "Found upgradeable file, kill LaunchActivity"); |
2416 | - InstallActivity.startFrom(context); |
2417 | - finish(); |
2418 | - } |
2419 | + public void onReceive(Context context, Intent intent) { |
2420 | + String action = intent.getAction(); |
2421 | + if (action.equals(UbuntuInstallService.SERVICE_STATE_CHANGED)) { |
2422 | + InstallerState newState = mInstallerService.getServiceState(); |
2423 | + Log.d(TAG,"New Service state:" + newState); |
2424 | + switch(newState) { |
2425 | + case DOWNLOADING: |
2426 | + case INSTALLING: |
2427 | + // switch back to install activity to minitor ongoing task |
2428 | + InstallActivity.startFrom(context); |
2429 | + finish(); |
2430 | + break; |
2431 | + default: |
2432 | + checkActivityStillValid(); |
2433 | + break; |
2434 | + } |
2435 | + } else if (action.equals(UbuntuInstallService.STORAGE_USE_UPDATED)) { |
2436 | + updateUiElements(); |
2437 | + }else if (action.equals(UbuntuInstallService.ANDROID_UPDATE_PENDING)) { |
2438 | + if (!mSharedPreferences.getBoolean(UbuntuInstallService.PREF_KEY_ANDROID_UPDATE_DISMISSED, false)) { |
2439 | + mAndroidUpdatePending = true; |
2440 | + } |
2441 | + if (mMenu != null) { |
2442 | + mMenu.findItem(R.id.menu_action_update_android).setShowAsAction( MenuItem.SHOW_AS_ACTION_ALWAYS); |
2443 | + } |
2444 | + updateUiElements(); |
2445 | + } else if (action.equals(UbuntuInstallService.UBUNTU_UPDATE_PENDING)) { |
2446 | + mUpdateButton.setVisibility(View.VISIBLE); |
2447 | + } else if (action.equals(UbuntuInstallService.UBUNTU_UPDATE_AVAILABLE)) { |
2448 | + mUpdateButton.setVisibility(View.VISIBLE); |
2449 | } |
2450 | + |
2451 | } |
2452 | }; |
2453 | } |
2454 | |
2455 | === modified file 'src/com/canonical/ubuntu/installer/NumberPickerDialog.java' |
2456 | --- src/com/canonical/ubuntu/installer/NumberPickerDialog.java 2013-12-13 01:06:14 +0000 |
2457 | +++ src/com/canonical/ubuntu/installer/NumberPickerDialog.java 2014-06-09 11:59:50 +0000 |
2458 | @@ -1,3 +1,20 @@ |
2459 | +/* |
2460 | + * This file is part of Ubuntu dualboot installer for Android. |
2461 | + * Copyright 2013 Canonical Ltd. |
2462 | + * |
2463 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
2464 | + * it under the terms of the GNU General Public License as published by |
2465 | + * the Free Software Foundation. |
2466 | + * |
2467 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
2468 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2469 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
2470 | + * See the GNU General Public License for more details. |
2471 | + * |
2472 | + * You should have received a copy of the GNU General Public License |
2473 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
2474 | + */ |
2475 | + |
2476 | package com.canonical.ubuntu.installer; |
2477 | |
2478 | import com.canonical.ubuntu.installer.R; |
2479 | @@ -5,15 +22,12 @@ |
2480 | import android.app.AlertDialog; |
2481 | import android.content.Context; |
2482 | import android.content.DialogInterface; |
2483 | -import android.content.SharedPreferences; |
2484 | import android.content.DialogInterface.OnClickListener; |
2485 | import android.content.res.Resources; |
2486 | import android.os.Bundle; |
2487 | import android.view.LayoutInflater; |
2488 | import android.view.View; |
2489 | -import android.widget.CheckBox; |
2490 | import android.widget.NumberPicker; |
2491 | -import android.widget.TextView; |
2492 | |
2493 | /** |
2494 | * A text picker dialog that prompts the user for to select one of the text options |
2495 | |
2496 | === modified file 'src/com/canonical/ubuntu/installer/TextPickerDialog.java' |
2497 | --- src/com/canonical/ubuntu/installer/TextPickerDialog.java 2013-12-13 01:06:14 +0000 |
2498 | +++ src/com/canonical/ubuntu/installer/TextPickerDialog.java 2014-06-09 11:59:50 +0000 |
2499 | @@ -1,3 +1,20 @@ |
2500 | +/* |
2501 | + * This file is part of Ubuntu dualboot installer for Android. |
2502 | + * Copyright 2013 Canonical Ltd. |
2503 | + * |
2504 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
2505 | + * it under the terms of the GNU General Public License as published by |
2506 | + * the Free Software Foundation. |
2507 | + * |
2508 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
2509 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2510 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
2511 | + * See the GNU General Public License for more details. |
2512 | + * |
2513 | + * You should have received a copy of the GNU General Public License |
2514 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
2515 | + */ |
2516 | + |
2517 | package com.canonical.ubuntu.installer; |
2518 | |
2519 | import com.canonical.ubuntu.installer.R; |
2520 | @@ -13,7 +30,6 @@ |
2521 | import android.view.View; |
2522 | import android.widget.CheckBox; |
2523 | import android.widget.NumberPicker; |
2524 | -import android.widget.TextView; |
2525 | |
2526 | /** |
2527 | * A text picker dialog that prompts the user for to select one of the text options |
2528 | |
2529 | === modified file 'src/com/canonical/ubuntu/installer/UbuntuInstallService.java' |
2530 | --- src/com/canonical/ubuntu/installer/UbuntuInstallService.java 2014-01-06 15:07:12 +0000 |
2531 | +++ src/com/canonical/ubuntu/installer/UbuntuInstallService.java 2014-06-09 11:59:50 +0000 |
2532 | @@ -1,7 +1,25 @@ |
2533 | +/* |
2534 | + * This file is part of Ubuntu dualboot installer for Android. |
2535 | + * Copyright 2013 Canonical Ltd. |
2536 | + * |
2537 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
2538 | + * it under the terms of the GNU General Public License as published by |
2539 | + * the Free Software Foundation. |
2540 | + * |
2541 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
2542 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2543 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
2544 | + * See the GNU General Public License for more details. |
2545 | + * |
2546 | + * You should have received a copy of the GNU General Public License |
2547 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
2548 | + */ |
2549 | + |
2550 | package com.canonical.ubuntu.installer; |
2551 | |
2552 | import java.io.DataOutputStream; |
2553 | import java.io.File; |
2554 | +import java.io.FileFilter; |
2555 | import java.io.FileNotFoundException; |
2556 | import java.io.FileOutputStream; |
2557 | import java.io.IOException; |
2558 | @@ -22,18 +40,49 @@ |
2559 | import org.json.JSONTokener; |
2560 | |
2561 | import com.canonical.ubuntu.installer.JsonChannelParser.Image; |
2562 | -import com.canonical.ubuntu.installer.VersionInfo.ReleaseType; |
2563 | |
2564 | +import android.annotation.SuppressLint; |
2565 | import android.app.IntentService; |
2566 | +import android.app.Notification; |
2567 | +import android.app.NotificationManager; |
2568 | +import android.app.PendingIntent; |
2569 | import android.content.Context; |
2570 | import android.content.Intent; |
2571 | +import android.content.IntentFilter; |
2572 | import android.content.SharedPreferences; |
2573 | +import android.net.ConnectivityManager; |
2574 | +import android.net.NetworkInfo; |
2575 | +import android.net.wifi.WifiManager; |
2576 | +import android.os.BatteryManager; |
2577 | +import android.os.Binder; |
2578 | +import android.os.Build; |
2579 | +import android.os.IBinder; |
2580 | import android.os.PowerManager; |
2581 | import android.util.Log; |
2582 | import android.webkit.URLUtil; |
2583 | |
2584 | public class UbuntuInstallService extends IntentService { |
2585 | private static final String TAG = "UbuntuInstallService"; |
2586 | + |
2587 | + // ================================================================================================= |
2588 | + // Behaviour constants |
2589 | + // ================================================================================================= |
2590 | + // Default update server address |
2591 | + public static final String SERVER_URL = "http://system-image.ubuntu.com"; |
2592 | + // Flag if channel list should also include hidden channels |
2593 | + private static final boolean INCLUDE_HIDDEN = false; |
2594 | + // Flag if channel list should include saucy channels |
2595 | + private static final boolean INCLUDE_SAUCY = false; |
2596 | + // How often service should check for update for normal channel |
2597 | + public static final int UPDATE_CHECK_ALARM_HOURS = 48; // every 2 days |
2598 | + // How often service should check for update for proposed channel |
2599 | + public static final int UPDATE_CHECK_PROPOSED_ALARM_HOURS = 10; // every 10 hours |
2600 | + |
2601 | + // Minimum battery charge in % for install to progress |
2602 | + public static final int MIN_INSTALL_BATTERY_CHARGE = 30; |
2603 | + |
2604 | + // Bring up mode, support any device |
2605 | + public static final boolean BRINGUP_MODE = false; |
2606 | |
2607 | // ================================================================================================= |
2608 | // Shared preferences |
2609 | @@ -41,14 +90,41 @@ |
2610 | public final static String SHARED_PREF = "UInstallerPref"; |
2611 | // Key for string value: absolute path to update file |
2612 | public final static String PREF_KEY_UPDATE_COMMAND = "update_command"; |
2613 | - // Key for String set value: version information: alias, Json, version, description |
2614 | - private final static String PREF_KEY_DOWNLOADED_VERSION = "d_version"; |
2615 | - // Key for String set value: version information: alias, Json, version, description |
2616 | - private final static String PREF_KEY_INSTALLED_VERSION = "i_version"; |
2617 | + |
2618 | + // Key strings describing active download |
2619 | + public final static String PREF_KEY_DOWNLOAD_ACTIVE = "d_active"; |
2620 | + public final static String PREF_KEY_DOWNLOAD_SERVER = "server_url"; |
2621 | + public final static String PREF_KEY_DOWNLOAD_CHANNEL = "channel_json"; |
2622 | + public final static String PREF_KEY_DOWNLOAD_BOOTSTRAP = "bootstrap"; |
2623 | + public final static String PREF_KEY_DOWNLOAD_VERSION = "d_version"; |
2624 | + public final static String PREF_KEY_DOWNLOAD_TYPE = "d_type"; |
2625 | + public final static String PREF_KEY_DOWNLOAD_COMPLETED = "d_completed"; |
2626 | + |
2627 | + // Key strings describing installed version |
2628 | + public static final String PREF_KEY_VERSION_NUMBER = "version_number"; |
2629 | + public static final String PREF_KEY_VERSION_CHANNEL = "version_channel"; |
2630 | + public static final String PREF_KEY_VERSION_CHANNEL_TARGET = "version_channel_target"; |
2631 | + public static final String PREF_KEY_VERSION_DESCRIPTION = "version_description"; |
2632 | + public static final String PREF_KEY_VERSION_BASE = "version_base"; |
2633 | + |
2634 | + public static final String PREF_KEY_UBUNTU_INSTALLED = "u_installed"; |
2635 | + |
2636 | + // Key for pending update, type boolean |
2637 | + public static final String PREF_KEY_PENDING_UPDATE = "pending_update"; |
2638 | + |
2639 | + // Key for android update notification being dismissed, type boolean |
2640 | + public static final String PREF_KEY_ANDROID_UPDATE_DISMISSED = "android_u_dismissed"; |
2641 | + |
2642 | // Key for boolean value: true if developer option is enabled |
2643 | public final static String PREF_KEY_DEVELOPER = "developer"; |
2644 | - // Key for int value: estimated number of checkpoints for installation |
2645 | - public final static String PREF_KEY_ESTIMATED_CHECKPOINTS = "est_checkpoints"; |
2646 | + |
2647 | + // Kyes describing occupied storage space, all values are stored as string |
2648 | + // key for int value: rootfs size in MB |
2649 | + public final static String PREF_KEY_SIZE_ROOTFS = "size_rootfs"; |
2650 | + // key for int value: system data size in MB |
2651 | + public final static String PREF_KEY_SIZE_SYSTEM_DATA = "size_system_data"; |
2652 | + // key for int value: user data size in MB |
2653 | + public final static String PREF_KEY_SIZE_USER_DATA = "size_user_data"; |
2654 | |
2655 | // ================================================================================================= |
2656 | // Default values to be used |
2657 | @@ -70,66 +146,69 @@ |
2658 | public final static String MAKO_PARTITION_RECOVERY = "/dev/block/platform/msm_sdcc.1/by-name/recovery"; |
2659 | public final static String MANTA_PARTITION_BOOT = "/dev/block/platform/dw_mmc.0/by-name/boot"; |
2660 | public final static String MANTA_PARTITION_RECOVERY = "/dev/block/platform/dw_mmc.0/by-name/recovery"; |
2661 | + public final static String DEFAULT_PARTITION_BOOT = "/dev/bootimg"; // this is used for bringup devices |
2662 | + public final static String DEFAULT_PARTITION_RECOVERY = "/dev/recovery"; // this is used for bringup devices |
2663 | + |
2664 | + |
2665 | + // ================================================================================================= |
2666 | + // Ubuntu parts |
2667 | + // ================================================================================================= |
2668 | + public static final String UBUNTU_ROOTFS = "/data/system.img"; |
2669 | + public static final String UBUNTU_SYSTEM_DATA = "/data/system-data"; |
2670 | + public static final String UBUNTU_USER_DATA = "/data/user-data"; |
2671 | |
2672 | // ================================================================================================= |
2673 | // Service Actions |
2674 | + public static final String BASE_PACKAGE = "com.canonical.ubuntuinstaller.UbuntuInstallService."; |
2675 | // ================================================================================================= |
2676 | // Get list of channels |
2677 | - public static final String GET_CHANNEL_LIST = "com.canonical.ubuntuinstaller.UbuntuInstallService.GET_CHANNEL_LIST"; |
2678 | + public static final String GET_CHANNEL_LIST = BASE_PACKAGE + "GET_CHANNEL_LIST"; |
2679 | + public static final String GET_CHANNEL_LIST_EXTRA_SERVER_URL = "url"; // string |
2680 | // Download latest release from given channel |
2681 | - public static final String DOWNLOAD_RELEASE = "com.canonical.ubuntuinstaller.UbuntuInstallService.DOWNLOAD_RELEASE"; |
2682 | - public static final String DOWNLOAD_RELEASE_EXTRA_CHANNEL_ALIAS = "alias"; // string |
2683 | - public static final String DOWNLOAD_RELEASE_EXTRA_CHANNEL_URL = "url"; // string |
2684 | - public static final String DOWNLOAD_RELEASE_EXTRA_BOOTSTRAP = "bootstrap"; // boolean |
2685 | - public static final String DOWNLOAD_RELEASE_EXTRA_VERSION = "version"; // int |
2686 | - public static final String DOWNLOAD_RELEASE_EXTRA_TYPE = "type"; // JsonChannelParser.ReleaseType |
2687 | - public static final String CANCEL_DOWNLOAD = "com.canonical.ubuntuinstaller.UbuntuInstallService.CANCEL_DOWNLOAD"; |
2688 | - public static final String PAUSE_DOWNLOAD = "com.canonical.ubuntuinstaller.UbuntuInstallService.PAUSE_DOWNLOAD"; |
2689 | - public static final String RESUME_DOWNLOAD = "com.canonical.ubuntuinstaller.UbuntuInstallService.RESUME_DOWNLOAD"; |
2690 | - public static final String CLEAN_DOWNLOAD = "com.canonical.ubuntuinstaller.UbuntuInstallService.CLEAN_DOWNLOADED"; |
2691 | - public static final String INSTALL_UBUNTU = "com.canonical.ubuntuinstaller.UbuntuInstallService.INSTALL_UBUNTU"; |
2692 | - public static final String CANCEL_INSTALL = "com.canonical.ubuntuinstaller.UbuntuInstallService.CANCEL_INSTALL"; |
2693 | - public static final String UNINSTALL_UBUNTU = "com.canonical.ubuntuinstaller.UbuntuInstallService.UINSTALL_UBUNTU"; |
2694 | - public static final String IS_UBUNTU_UPGRADABLE = "com.canonical.ubuntuinstaller.UbuntuInstallService.IS_UBUNTU_UPGRADABLE"; |
2695 | - public static final String UNINSTALL_UBUNTU_EXTRA_REMOVE_USER_DATA = "user_data"; |
2696 | - public static final String CHECK_FOR_UPDATE = "com.canonical.ubuntuinstaller.UbuntuInstallService.CHECK_FOR_UPDATE"; |
2697 | - public static final String DELETE_UBUNTU_USER_DATA = "com.canonical.ubuntuinstaller.UbuntuInstallService.DELETE_USER_DATA"; |
2698 | - public static final String GET_SERVICE_STATE = "com.canonical.ubuntuinstaller.UbuntuInstallService.GET_SERVICE_STATE"; |
2699 | - public static final String GET_PROGRESS_STATUS = "com.canonical.ubuntuinstaller.UbuntuInstallService.GET_PROGRESS_STATUS"; |
2700 | - public static final String REBOOT_UBUNTU = "com.canonical.ubuntuinstaller.UbuntuInstallService.REBOOT_UBUNTU"; |
2701 | + public static final String DOWNLOAD_RELEASE = BASE_PACKAGE + "DOWNLOAD_RELEASE"; |
2702 | + public static final String DOWNLOAD_RELEASE_EXTRA_SERVER_URL = "url_server"; // string |
2703 | + public static final String DOWNLOAD_RELEASE_EXTRA_CHANNEL_URL = "url_channel"; // string |
2704 | + public static final String DOWNLOAD_RELEASE_EXTRA_BOOTSTRAP = "bootstrap"; // boolean |
2705 | + public static final String DOWNLOAD_RELEASE_EXTRA_VERSION = "version"; // int |
2706 | + public static final String DOWNLOAD_RELEASE_EXTRA_TYPE = "type"; // JsonChannelParser.ReleaseType |
2707 | + public static final String DOWNLOAD_UPDATE = BASE_PACKAGE + "DOWNLOAD_UPDATE"; |
2708 | + public static final String RESUME_DOWNLOAD = BASE_PACKAGE + "RESUME_DOWNLOAD"; |
2709 | + public static final String DELETE_DOWNLOAD = BASE_PACKAGE + "DELETE_DOWNLOAD"; |
2710 | + public static final String INSTALL_UBUNTU = BASE_PACKAGE + "INSTALL_UBUNTU"; |
2711 | + public static final String UNINSTALL_UBUNTU = BASE_PACKAGE + "UINSTALL_UBUNTU"; |
2712 | + public static final String UNINSTALL_UBUNTU_EXTRA_REMOVE_USER_DATA = "user_data"; |
2713 | + public static final String DELETE_UBUNTU_USER_DATA = BASE_PACKAGE + "DELETE_UBUNTU_USER_DATA"; |
2714 | + public static final String REBOOT_UBUNTU = BASE_PACKAGE + "REBOOT_UBUNTU"; |
2715 | + public static final String UPDATE_STORAGE_USE = BASE_PACKAGE + "UPDATE_STORAGE_USE"; |
2716 | + public static final String CHECK_IF_UPDATE_AVAILABLE = BASE_PACKAGE + "CHECK_IF_UPDATE_AVAILABLE"; |
2717 | + public static final String CHECK_PENDING_UPDATES = BASE_PACKAGE + "CHECK_PENDING_UPDATES"; |
2718 | + public static final String PREPARE_ANDROID_UPDATE = BASE_PACKAGE + "PREPARE_ANDROID_UPDATE"; |
2719 | |
2720 | // ================================================================================================= |
2721 | // Service broadcast |
2722 | // ================================================================================================= |
2723 | - public static final String SERVICE_STATE = "com.canonical.ubuntuinstaller.UbuntuInstallService.SERVICE_STATE"; |
2724 | - public static final String SERVICE_STATE_EXTRA_STATE = "state"; // InstallerState enum |
2725 | - public static final String AVAILABLE_CHANNELS = "com.canonical.ubuntuinstaller.UbuntuInstallService.AVAILABLE_CHANNELS"; |
2726 | - public static final String AVAILABLE_CHANNELS_EXTRA_CHANNELS = "channels"; // HashMap<String,String> channel aliases and json url |
2727 | - public static final String DOWNLOAD_RESULT = "com.canonical.ubuntuinstaller.UbuntuInstallService.DOWNLOAD_RESULT"; |
2728 | - public static final String DOWNLOAD_RESULT_EXTRA_INT = "res_int"; // 0-success, -1 fail |
2729 | - public static final String DOWNLOAD_RESULT_EXTRA_STR = "res_str"; // empty for success, or error text |
2730 | - public static final String PROGRESS = "com.canonical.ubuntuinstaller.UbuntuInstallService.PROGRESS"; |
2731 | - public static final String PROGRESS_EXTRA_TEXT = "text"; // value will carry name of file currently downloaded |
2732 | - public static final String PROGRESS_EXTRA_INT = "progress"; // value between 0-100 of current progress |
2733 | - public static final String INSTALL_RESULT = "com.canonical.ubuntuinstaller.UbuntuInstallService.INSTALL_COMPLETED"; |
2734 | - public static final String INSTALL_RESULT_EXTRA_INT = "res_int"; // 0-success, -1 fail |
2735 | - public static final String INSTALL_RESULT_EXTRA_STR = "res_str"; // empty for success, or error text |
2736 | - public static final String VERSION_UPDATE = "com.canonical.ubuntuinstaller.UbuntuInstallService.VERSION_UPDATE"; |
2737 | - public static final String VERSION_UPDATE_EXTRA_VERSION = "version"; // int new version |
2738 | - public static final String VERSION_UPDATE_EXTRA_DESCRIPTION = "description"; // string |
2739 | - public static final String VERSION_UPDATE_EXTRA_ALIAS = "alias"; // string |
2740 | + public static final String SERVICE_STATE_CHANGED = BASE_PACKAGE + "SERVICE_STATE"; |
2741 | + public static final String AVAILABLE_CHANNELS = BASE_PACKAGE + "AVAILABLE_CHANNELS"; |
2742 | + public static final String AVAILABLE_CHANNELS_EXTRA_CHANNELS = "channels"; // HashMap<String,String> channel aliases and json url |
2743 | + public static final String DOWNLOAD_RESULT = BASE_PACKAGE + "DOWNLOAD_RESULT"; |
2744 | + public static final String DOWNLOAD_RESULT_EXTRA_INT = "res_int"; // 0-success, -1 fail |
2745 | + public static final String DOWNLOAD_RESULT_EXTRA_STR = "res_str"; // empty for success, or error text |
2746 | + public static final String PROGRESS = BASE_PACKAGE + "PROGRESS"; |
2747 | + public static final String PROGRESS_OUPUT = BASE_PACKAGE + "PROGRESS_OUTPUT"; |
2748 | + public static final String INSTALL_RESULT = BASE_PACKAGE + "INSTALL_COMPLETED"; |
2749 | + public static final String INSTALL_RESULT_EXTRA_INT = "res_int"; // 0-success, -1 fail |
2750 | + public static final String INSTALL_RESULT_EXTRA_STR = "res_str"; // empty for success, or error text |
2751 | + public static final String STORAGE_USE_UPDATED = BASE_PACKAGE + "STORAGE_USE_UPDATED"; |
2752 | + public static final String ANDROID_UPDATE_PENDING = BASE_PACKAGE + "ANDROID_UPDATE"; |
2753 | + public static final String UBUNTU_UPDATE_PENDING = BASE_PACKAGE + "UBUNTU_UPDATE_PENDING"; |
2754 | + public static final String UBUNTU_UPDATE_AVAILABLE = BASE_PACKAGE + "UBUNTU_UPDATE_AVAILABLE"; |
2755 | |
2756 | // ================================================================================================= |
2757 | - // Download url strings |
2758 | + // Other constants |
2759 | // ================================================================================================= |
2760 | - public static final String BASE_URL = "http://system-image.ubuntu.com"; |
2761 | private static final String CHANNELS_JSON = "/channels.json"; |
2762 | - private static final String URL_IMAGE_MASTER = "gpg/image-master.tar.xz"; |
2763 | - private static final String URL_IMAGE_SIGNING = "gpg/image-signing.tar.xz"; |
2764 | - private static final String ASC_SUFFIX = ".asc"; |
2765 | - |
2766 | - // 2G for file system, 512M for swap. |
2767 | - private static long INSTALL_SIZE_REQUIRED = (2048L + 512L) * 1024L * 1024L; |
2768 | + // 2G for file system |
2769 | + private static long INSTALL_SIZE_REQUIRED = 2048L * 1024L * 1024L; |
2770 | // 15M extra space to keep it safe. |
2771 | private static long EXTRA_SIZE_REQUIRED = 15 * 1024 * 1024; |
2772 | |
2773 | @@ -138,7 +217,7 @@ |
2774 | * State of the service |
2775 | */ |
2776 | public enum InstallerState { |
2777 | - READY, FETCHING_CHANNELS, DOWNLOADING, INSTALLING, UNINSTALLING, DELETING_USER_DATA; |
2778 | + READY, FETCHING_CHANNELS, DOWNLOADING, INSTALLING, UNINSTALLING, DELETING_USER_DATA, CALCULATING_USAGE; |
2779 | public static InstallerState fromOrdian(int ordianl) { |
2780 | return InstallerState.values()[ordianl]; |
2781 | } |
2782 | @@ -152,53 +231,76 @@ |
2783 | private static final String TAR = "u_tar"; |
2784 | private static final String ANDROID_LOOP_MOUNT = "aloopmount"; |
2785 | private static final String ANDROID_BOOTMGR = "bootmgr"; |
2786 | - private static final String UPGRADECHECKER = "upgrade-checker"; |
2787 | private static final String UPDATE_SCRIPT = "system-image-upgrader"; |
2788 | - private static final String ARCHIVE_MASTER = "archive-master.tar.xz"; |
2789 | - private static final String ARCHIVE_MASTER_ASC = "archive-master.tar.xz.asc"; |
2790 | - private static final String U_REBOOT_APP = "u-reboot-app.tar.xz"; |
2791 | - private static final String U_REBOOT_APP_ASC = "u-reboot-app.tar.xz.asc"; |
2792 | + public static final String U_REBOOT_APP = "u-reboot-app.tar.xz"; |
2793 | + public static final String RECOVERY_REMOUNT = "recovery-remount.tar.xz"; |
2794 | |
2795 | // ================================================================================================= |
2796 | // Update command file constants |
2797 | - // ================================================================================================= |
2798 | - private static final String UPDATE_COMMAND = "update_command"; |
2799 | - private static final String COMMAND_FORMAT = "format"; |
2800 | - private static final String COMMAND_MOUNT = "mount"; |
2801 | - private static final String COMMAND_UMOUNT = "unmount"; |
2802 | - private static final String COMMAND_LOAD_KEYRING = "load_keyring"; |
2803 | - private static final String COMMAND_UPDATE = "update"; |
2804 | - private static final String PARTITION_DATA = "data"; |
2805 | - private static final String PARTITION_SYSTEM = "system"; |
2806 | + // ================================================================================================= |
2807 | + public static final String UPDATE_COMMAND = "update_command"; |
2808 | + public static final String COMMAND_FORMAT = "format"; |
2809 | + public static final String COMMAND_MOUNT = "mount"; |
2810 | + public static final String COMMAND_UMOUNT = "unmount"; |
2811 | + public static final String COMMAND_UPDATE = "update"; |
2812 | + public static final String PARTITION_DATA = "data"; |
2813 | + public static final String PARTITION_SYSTEM = "system"; |
2814 | |
2815 | // other constants |
2816 | + public static final String CUSTOM_SERVER="custom_server"; |
2817 | private static final String RELEASE_FOLDER = "/ubuntu_release"; |
2818 | + private static final String LINKED_UPGRADER_COMMAND = "recovery/ubuntu_command"; |
2819 | + private static final String PENDING_ANDROID_UPDATE = "android_update"; |
2820 | private static final String TEMP_FOLDER = "/uTemp"; |
2821 | private static final int PROGRESS_UBUNTU_ADJUSTMENT = 563979; |
2822 | private static final int PROGRESS_DEVICE_ADJUSTMENT = 651093; |
2823 | private static final int PROGRESS_CUSTOM_ADJUSTMENT = 2036039; |
2824 | - private static final int PROGRESS_SWAP_CREATION_ADJUSTMENT = 85; // equivalent of time tar --checkpoint=200 |
2825 | - private static final int PROGRESS_MKSWAP_ADJUSTMENT = 17; // equivalent of time tar --checkpoint=200 |
2826 | - private PowerManager mPowerManager; |
2827 | private PowerManager.WakeLock mWakeLock; |
2828 | - // FIXME make workPath in Cache a private function |
2829 | - private boolean workPathInCache = false; |
2830 | - private String mRootOfWorkPath; |
2831 | + private WifiManager.WifiLock mWifiLock; |
2832 | private volatile boolean mIsCanceled; |
2833 | + private boolean mBringup; |
2834 | |
2835 | // progress values |
2836 | private long mProgress; // so far handled amount downloaded/processed |
2837 | private int mLastSignalledProgress; |
2838 | + private String mActionOutput; |
2839 | private long mTotalSize; // calculated |
2840 | - private InstallerState mInstallerState; |
2841 | + private InstallerState mServiceState; |
2842 | + private File mReleaseFolder; |
2843 | + private SharedPreferences mSharedPreferences; |
2844 | + private Notification mUbuntuNotification; |
2845 | + private Notification mUbuntuUpdateNotification; |
2846 | + private Notification mUbuntuProgressNotification; |
2847 | + private Notification mAndroidUpdateNotification; |
2848 | + NotificationManager mNotificationManager; |
2849 | |
2850 | - public class Channel { |
2851 | - String alias; |
2852 | - File[] files; |
2853 | - boolean hiden; |
2854 | + public enum ReleaseType { |
2855 | + FULL(0), |
2856 | + DELTA(1), |
2857 | + UNKNOWN(2); |
2858 | + private final int value; |
2859 | + |
2860 | + private ReleaseType(final int newValue) { |
2861 | + value = newValue; |
2862 | + } |
2863 | + |
2864 | + public int getValue() { |
2865 | + return value; |
2866 | + } |
2867 | + |
2868 | + public static ReleaseType fromValue(final int value) { |
2869 | + switch (value) { |
2870 | + case 0: // FULL |
2871 | + return FULL; |
2872 | + case 1: // DELTA |
2873 | + return DELTA; |
2874 | + } |
2875 | + return UNKNOWN; |
2876 | + } |
2877 | }; |
2878 | |
2879 | class ECancelException extends Exception { |
2880 | + private static final long serialVersionUID = 1L; |
2881 | long mDownloadedSize; |
2882 | |
2883 | public ECancelException(long downloadedSize){ |
2884 | @@ -208,6 +310,8 @@ |
2885 | }; |
2886 | |
2887 | class ESumNotMatchException extends Exception { |
2888 | + private static final long serialVersionUID = 1L; |
2889 | + |
2890 | public ESumNotMatchException(){ |
2891 | super(); |
2892 | } |
2893 | @@ -218,6 +322,7 @@ |
2894 | }; |
2895 | |
2896 | class EShellExecException extends Exception { |
2897 | + private static final long serialVersionUID = 1L; |
2898 | public EShellExecException(){ |
2899 | super(); |
2900 | } |
2901 | @@ -228,134 +333,195 @@ |
2902 | }; |
2903 | |
2904 | public UbuntuInstallService() { |
2905 | - super(TAG); |
2906 | - } |
2907 | + super(UbuntuInstallService.class.getName()); |
2908 | + } |
2909 | + |
2910 | + /** |
2911 | + * Class for clients to get hold of this service |
2912 | + * this only works as long as service runs in same process as client |
2913 | + */ |
2914 | + public class LocalBinder extends Binder { |
2915 | + UbuntuInstallService getService() { |
2916 | + return UbuntuInstallService.this; |
2917 | + } |
2918 | + } |
2919 | + |
2920 | + @Override |
2921 | + public IBinder onBind(Intent intent) { |
2922 | + return mBinder; |
2923 | + } |
2924 | + private final IBinder mBinder = new LocalBinder(); |
2925 | |
2926 | @Override |
2927 | public void onCreate() { |
2928 | super.onCreate(); |
2929 | - mPowerManager = (PowerManager)getSystemService(Context.POWER_SERVICE); |
2930 | - // SharedPreferences sharedPref = this.getSharedPreferences(, MODE_PRIVATE); |
2931 | - // do we have cache permissions? |
2932 | - File testDir = new File("/cache/testDir"); |
2933 | - if (testDir.mkdir()) { |
2934 | - testDir.delete(); |
2935 | - mRootOfWorkPath = "/cache"; |
2936 | - workPathInCache = true; |
2937 | - } else { |
2938 | - mRootOfWorkPath = getFilesDir().toString(); // "/data/data/com.canonical.ubuntu.installer/files"; |
2939 | - workPathInCache = false; |
2940 | - } |
2941 | - mInstallerState = InstallerState.READY; |
2942 | - } |
2943 | - |
2944 | - @Override |
2945 | - public int onStartCommand(Intent intent, int flags, int startId) { |
2946 | - // if service is not in ready state, handle specific requests here |
2947 | - if (mInstallerState != InstallerState.READY) { |
2948 | - String action = intent.getAction(); |
2949 | - if (action.equals(CANCEL_DOWNLOAD)) { |
2950 | - // set the cancel flag, but let it remove downloaded files on worker thread |
2951 | - mIsCanceled = true; |
2952 | - } else if (action.equals(GET_PROGRESS_STATUS)) { |
2953 | - broadcastProgress(mLastSignalledProgress, ""); |
2954 | - } else if (action.equals(GET_SERVICE_STATE)) { |
2955 | - broadcastInstallerState(); |
2956 | - } |
2957 | - } |
2958 | - return super.onStartCommand(intent, flags, startId); |
2959 | - } |
2960 | - |
2961 | + mReleaseFolder = new File(getFilesDir(), RELEASE_FOLDER); |
2962 | + mServiceState = InstallerState.READY; |
2963 | + mSharedPreferences = getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE); |
2964 | + mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); |
2965 | + mWakeLock = ((PowerManager)getSystemService(Context.POWER_SERVICE)) |
2966 | + .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ubuntu-dualboot"); |
2967 | + WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE); |
2968 | + mWifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, TAG); |
2969 | + mBringup = Utils.isBringupMode(); |
2970 | + } |
2971 | + |
2972 | + /** |
2973 | + * Get service state |
2974 | + * @return service state |
2975 | + */ |
2976 | + public InstallerState getServiceState(){ |
2977 | + return mServiceState; |
2978 | + } |
2979 | + |
2980 | + /** |
2981 | + * Get ongoing action progress |
2982 | + * @return last known progress |
2983 | + */ |
2984 | + public int getActionProgress() { |
2985 | + return mLastSignalledProgress; |
2986 | + } |
2987 | + |
2988 | + /** |
2989 | + * Pause ongoing download |
2990 | + */ |
2991 | + public void pauseDownload() { |
2992 | + if (mServiceState == InstallerState.DOWNLOADING) { |
2993 | + mIsCanceled = true; |
2994 | + } |
2995 | + } |
2996 | + |
2997 | + /** |
2998 | + * Get action output |
2999 | + * @return action output buffer |
3000 | + */ |
3001 | + public String getActionOutput() { |
3002 | + return mActionOutput; |
3003 | + } |
3004 | + |
3005 | + /** |
3006 | + * Reset action output buffer |
3007 | + */ |
3008 | + public void resetActionOutput() { |
3009 | + mActionOutput = ""; |
3010 | + } |
3011 | + |
3012 | @Override |
3013 | protected void onHandleIntent(Intent intent) { |
3014 | + // reset progress for new action |
3015 | + if (intent == null) { |
3016 | + // ignore |
3017 | + return; |
3018 | + } |
3019 | + mLastSignalledProgress = 0; |
3020 | String action = intent.getAction(); |
3021 | + String debugAction = action; |
3022 | + if (action.startsWith(BASE_PACKAGE)) { |
3023 | + debugAction = action.substring(BASE_PACKAGE.length()); |
3024 | + } |
3025 | + Log.d(TAG, "onHandleIntent<<: " + debugAction); |
3026 | Intent result = null; |
3027 | - |
3028 | - Log.d(TAG, this.toString() + " onHandleIntent: " + action); |
3029 | if (action.equals(GET_CHANNEL_LIST)) { |
3030 | updateInstallerState(InstallerState.FETCHING_CHANNELS); |
3031 | - result = doGetChannelList(intent); |
3032 | + result = getChannelList(intent); |
3033 | } else if (action.equals(DOWNLOAD_RELEASE)) { |
3034 | updateInstallerState(InstallerState.DOWNLOADING); |
3035 | - result = doDownloadRelease(intent); |
3036 | - } else if (action.equals(CANCEL_DOWNLOAD)) { |
3037 | - // download should be already cancelled, don't delete files for might resume latter |
3038 | - // result = doRemoreDownload(intent); |
3039 | - result = new Intent(SERVICE_STATE); |
3040 | - result.putExtra(SERVICE_STATE_EXTRA_STATE, mInstallerState.ordinal()); |
3041 | - } else if (action.equals(PAUSE_DOWNLOAD)) { |
3042 | - // TODO: handle download |
3043 | + result = downloadRelease(intent); |
3044 | + } else if (action.equals(DOWNLOAD_UPDATE)) { |
3045 | + updateInstallerState(InstallerState.DOWNLOADING); |
3046 | + result = downloadUpdate(); |
3047 | } else if (action.equals(RESUME_DOWNLOAD)) { |
3048 | updateInstallerState(InstallerState.DOWNLOADING); |
3049 | - // TODO: handle download |
3050 | - } else if (action.equals(CLEAN_DOWNLOAD)) { |
3051 | - result = doRemoreDownload(intent); |
3052 | + result = resumeDownload(); |
3053 | + } else if (action.equals(DELETE_DOWNLOAD)) { |
3054 | + doDeleteDownloadedRelease(); |
3055 | } else if (action.equals(INSTALL_UBUNTU)) { |
3056 | updateInstallerState(InstallerState.INSTALLING); |
3057 | - result = doInstallUbuntu(intent); |
3058 | - } else if (action.equals(IS_UBUNTU_UPGRADABLE)) { |
3059 | + result = doInstallUbuntu(); |
3060 | + } else if (action.equals(CHECK_PENDING_UPDATES)) { |
3061 | // check if the upgradeable images available. |
3062 | - if(findInstallCommand()) { |
3063 | - Log.d(TAG, "There is a upgradeable file. send VERSION_UPDATE"); |
3064 | - result = new Intent(VERSION_UPDATE); |
3065 | - } |
3066 | - } else if (action.equals(CANCEL_INSTALL)) { |
3067 | - // install should be already cancelled, try to delete it now |
3068 | - updateInstallerState(InstallerState.UNINSTALLING); |
3069 | - result = doUninstallUbuntu(intent); |
3070 | + findPendingUpdates(); |
3071 | + } else if (action.equals(CHECK_IF_UPDATE_AVAILABLE)) { |
3072 | + checkForAvailableUpdate(); |
3073 | } else if (action.equals(UNINSTALL_UBUNTU)) { |
3074 | updateInstallerState(InstallerState.UNINSTALLING); |
3075 | - result = doUninstallUbuntu(intent); |
3076 | + doUninstallUbuntu(intent); |
3077 | } else if (action.equals(DELETE_UBUNTU_USER_DATA)) { |
3078 | updateInstallerState(InstallerState.DELETING_USER_DATA); |
3079 | - result = doDeleteUbuntuUserData(intent); |
3080 | + deleteUbuntuUserData(); |
3081 | } else if(action.equals(REBOOT_UBUNTU)) { |
3082 | - Log.d(TAG, this.toString() + ": REBOOT_UBUNTU"); |
3083 | - doReboot(intent); |
3084 | - return; |
3085 | + rebootToUbuntu(); |
3086 | + return; |
3087 | + } else if (action.equals(PREPARE_ANDROID_UPDATE)) { |
3088 | + prepareAndroidUpdate(); |
3089 | + return; |
3090 | + } else if (action.equals(UPDATE_STORAGE_USE)) { |
3091 | + updateInstallerState(InstallerState.CALCULATING_USAGE); |
3092 | + doUpdateStorageUse(); |
3093 | } else { |
3094 | // for any other request broadcast service state |
3095 | - result = new Intent(SERVICE_STATE); |
3096 | - result.putExtra(SERVICE_STATE_EXTRA_STATE, mInstallerState.ordinal()); |
3097 | + result = new Intent(SERVICE_STATE_CHANGED); |
3098 | } |
3099 | if (result != null) { |
3100 | sendBroadcast(result); |
3101 | } |
3102 | updateInstallerState(InstallerState.READY); |
3103 | - Log.d(TAG, this.toString() + " onHandleIntent: " + action + " END"); |
3104 | + Log.d(TAG, " onHandleIntent>>: " + debugAction); |
3105 | } |
3106 | |
3107 | - private Intent doGetChannelList(Intent intent) { |
3108 | + private Intent getChannelList(Intent intent) { |
3109 | + String serverUrl = intent.getStringExtra(GET_CHANNEL_LIST_EXTRA_SERVER_URL); |
3110 | + if (serverUrl == null) { |
3111 | + // use default server |
3112 | + serverUrl = Utils.getReleaseServerUrl(this);; |
3113 | + } |
3114 | + boolean includeProposed = mSharedPreferences.getBoolean(PREF_KEY_DEVELOPER, false); |
3115 | + HashMap<String, String> channels = doGetChannels(serverUrl, true, INCLUDE_SAUCY, INCLUDE_HIDDEN, includeProposed ); |
3116 | Intent result = new Intent(AVAILABLE_CHANNELS); |
3117 | - |
3118 | - HashMap<String, String> channels= new HashMap<String, String>(); |
3119 | - boolean includeHidden = getSharedPreferences( SHARED_PREF, Context.MODE_PRIVATE).getBoolean(PREF_KEY_DEVELOPER, false); |
3120 | + result.putExtra(AVAILABLE_CHANNELS_EXTRA_CHANNELS, channels); |
3121 | + return result; |
3122 | + } |
3123 | + |
3124 | + private HashMap<String, String> doGetChannels( String serverAddress, |
3125 | + boolean friendlyName, |
3126 | + boolean includeSaucy, |
3127 | + boolean includeHiden, |
3128 | + boolean includeProposed) { |
3129 | + HashMap<String, String> channels = new HashMap<String, String>(); |
3130 | String deviceModel = Utils.getDeviceModel(); |
3131 | - String channelJsonStr = Utils.httpDownload(BASE_URL + CHANNELS_JSON); |
3132 | + String channelJsonStr = Utils.httpDownload(serverAddress + CHANNELS_JSON); |
3133 | if (channelJsonStr != null) { |
3134 | JSONObject list; |
3135 | try { |
3136 | list = (JSONObject) new JSONTokener(channelJsonStr).nextValue(); |
3137 | + @SuppressWarnings("unchecked") |
3138 | Iterator<String> keys = list.keys(); |
3139 | while(keys.hasNext()){ |
3140 | String key = keys.next(); |
3141 | - JSONObject channel = list.optJSONObject(key); |
3142 | + final JSONObject channel = list.optJSONObject(key); |
3143 | if (channel != null) { |
3144 | - JSONObject devices = channel.optJSONObject("devices"); |
3145 | + final JSONObject devices = channel.optJSONObject("devices"); |
3146 | if (devices != null) { |
3147 | - JSONObject device = devices.optJSONObject(deviceModel); |
3148 | + final JSONObject device = devices.optJSONObject(deviceModel); |
3149 | if (device != null) { |
3150 | - String url = device.optString("index"); |
3151 | + final String url = device.optString("index"); |
3152 | if (url != null) { |
3153 | // bingo, add to list if not hidden or developer |
3154 | - boolean hidden = channel.optBoolean("hiden"); // by default not hidden |
3155 | - String alias = channel.optString("alias"); |
3156 | - if (alias == null || alias.equals("")) { |
3157 | - alias = key; // use key instead |
3158 | + final boolean hidden = channel.optBoolean("hidden"); // by default not hidden |
3159 | + // try to remove "ubuntu-touch/" so it's more human friendly |
3160 | + if (friendlyName && key.startsWith("ubuntu-touch/")) { |
3161 | + key = key.substring("ubuntu-touch/".length()); |
3162 | } |
3163 | - // Log.v(TAG, "Channel:" + alias + " url:" + url); |
3164 | - if (!hidden || includeHidden) { |
3165 | - channels.put(alias, url); |
3166 | + // Log.v(TAG, "Channel:" + key + " url:" + url); |
3167 | + if ( |
3168 | + ( includeSaucy || ! key.contains("saucy")) |
3169 | + && ( |
3170 | + !hidden |
3171 | + || includeHiden |
3172 | + || ( includeProposed && key.contains("-proposed")) |
3173 | + ) |
3174 | + ) { |
3175 | + channels.put(key, url); |
3176 | } |
3177 | } |
3178 | } |
3179 | @@ -363,44 +529,29 @@ |
3180 | } |
3181 | } |
3182 | } catch (JSONException e) { |
3183 | - // TODO Auto-generated catch block |
3184 | e.printStackTrace(); |
3185 | } |
3186 | } |
3187 | - result.putExtra(AVAILABLE_CHANNELS_EXTRA_CHANNELS, channels); |
3188 | - return result; |
3189 | + return channels; |
3190 | } |
3191 | |
3192 | - private Intent doRemoreDownload(Intent intent) { |
3193 | - Intent result = new Intent(SERVICE_STATE); |
3194 | - String s = deleteRelease(); |
3195 | - if (s!= null) { |
3196 | - broadcastProgress(-1, s); |
3197 | - // delete failed |
3198 | - } |
3199 | - result.putExtra(SERVICE_STATE, InstallerState.READY.ordinal()); |
3200 | - return result; |
3201 | - } |
3202 | - |
3203 | - private Intent doInstallUbuntu(Intent intent) { |
3204 | + private Intent doInstallUbuntu() { |
3205 | Log.w(TAG, "doInstallUbuntu"); |
3206 | Intent result = new Intent(INSTALL_RESULT); |
3207 | |
3208 | // get update command file |
3209 | String updateCommand = getUpdateCommand(); |
3210 | - |
3211 | - // 1. check if update command exist. |
3212 | - // 2. However, if the udpate command is in "/cache", |
3213 | - // the app can not access to /cache sometimes. |
3214 | + dismissUbuntuNotification(); |
3215 | + // check if update command exist. |
3216 | if (updateCommand.equals("") || |
3217 | - (!new File(updateCommand).exists() && |
3218 | - !updateCommand.startsWith("/cache"))) { |
3219 | - return handleInstallFail(result, -1, "Missing update command"); |
3220 | + (!new File(updateCommand).exists())) { |
3221 | + |
3222 | + return handleInstallError(result, -1, "Missing update command"); |
3223 | } |
3224 | |
3225 | - SharedPreferences pref = getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE); |
3226 | - mTotalSize = pref.getInt(PREF_KEY_ESTIMATED_CHECKPOINTS, 0); |
3227 | + mTotalSize = estimateCheckpooint(updateCommand); |
3228 | mLastSignalledProgress = 0; |
3229 | + mProgress = 0; |
3230 | |
3231 | List<String> shellcmds = new ArrayList<String>(); |
3232 | { |
3233 | @@ -427,37 +578,68 @@ |
3234 | UBUNTU_BOOT_IMG, |
3235 | Utils.getRecoveryPartitionPath() |
3236 | )); |
3237 | + // remove downloaded release |
3238 | + shellcmds.add(String.format("rm -rf %s\n", new File(updateCommand).getParent())); |
3239 | shellcmds.add("exit"); |
3240 | } |
3241 | |
3242 | - broadcastProgress(-1, "Starting update script - " + updateCommand); |
3243 | + broadcastProgress("Starting update script - " + updateCommand); |
3244 | try { |
3245 | int ret = executeSUCommands(shellcmds.toArray(new String[shellcmds.size()])); |
3246 | result.putExtra(INSTALL_RESULT_EXTRA_INT, ret); |
3247 | } catch (EShellExecException e) { |
3248 | - return handleInstallFail(result, -1, e.getMessage()); |
3249 | + return handleInstallError(result, -1, e.getMessage()); |
3250 | } |
3251 | - |
3252 | + Log.d(TAG, "doInstallUbuntu-update script finished"); |
3253 | + mLastSignalledProgress = 100; |
3254 | + handleInstallFinish(); |
3255 | + return result; |
3256 | + } |
3257 | + |
3258 | + /** |
3259 | + * Returns true if download or install is update operation |
3260 | + * @return |
3261 | + */ |
3262 | + private boolean isUpdate() { |
3263 | + // if not defined, default value is DELTA, for updates downloaded by Ubuntu upgrader |
3264 | + return ( ReleaseType.DELTA == ReleaseType.fromValue( |
3265 | + mSharedPreferences.getInt(PREF_KEY_DOWNLOAD_TYPE, ReleaseType.DELTA.getValue()))); |
3266 | + } |
3267 | + |
3268 | + private void handleInstallFinish() { |
3269 | // we done. |
3270 | + dismissUbuntuUpdateNotification(); |
3271 | cleanUpdateCommand(); |
3272 | - VersionInfo v = new VersionInfo(pref, PREF_KEY_DOWNLOADED_VERSION); |
3273 | - v.storeVersion(pref.edit(), PREF_KEY_INSTALLED_VERSION); |
3274 | - mProgress = 100; |
3275 | - return result; |
3276 | + checkChannelAddress(); |
3277 | + mSharedPreferences.edit() |
3278 | + .putBoolean(PREF_KEY_UBUNTU_INSTALLED, true) |
3279 | + .putBoolean(PREF_KEY_PENDING_UPDATE, false) |
3280 | + .commit(); |
3281 | + Utils.registerUpdateCheckAlarm(this, mSharedPreferences); |
3282 | + // update notifications |
3283 | + if ( isUpdate()) { |
3284 | + showUbuntuNotification(R.string.notification_update_installed, LaunchActivity.class); |
3285 | + } else { |
3286 | + showUbuntuNotification(R.string.notification_ubuntu_installed, LaunchActivity.class); |
3287 | + } |
3288 | } |
3289 | |
3290 | - private Intent handleInstallFail(Intent i, int res, String failReason) { |
3291 | + private Intent handleInstallError(Intent i, int res, String reason) { |
3292 | + mActionOutput += "\n" + reason; |
3293 | + if (isUpdate()) { |
3294 | + showUbuntuNotification(R.string.notification_installation_failed, LaunchActivity.class); |
3295 | + } else { |
3296 | + showUbuntuNotification(R.string.notification_installation_failed, InstallActivity.class); |
3297 | + } |
3298 | i.putExtra(INSTALL_RESULT_EXTRA_INT, -1); |
3299 | - i.putExtra(INSTALL_RESULT_EXTRA_STR, failReason); |
3300 | - // we don't want to unstainll if we failed to install a update. |
3301 | - // doUninstallUbuntu(i); |
3302 | + i.putExtra(INSTALL_RESULT_EXTRA_STR, reason); |
3303 | return i; |
3304 | } |
3305 | |
3306 | - private Intent doUninstallUbuntu(Intent intent) { |
3307 | - File workingFolder = new File(mRootOfWorkPath, TEMP_FOLDER); |
3308 | + private void doUninstallUbuntu(Intent intent) { |
3309 | + mActionOutput = ""; |
3310 | + File workingFolder = new File(getFilesDir(), TEMP_FOLDER); |
3311 | File updateCommand = new File(workingFolder, UPDATE_COMMAND); |
3312 | - Intent result = new Intent(VERSION_UPDATE); |
3313 | boolean removeUserData = intent.getBooleanExtra(UNINSTALL_UBUNTU_EXTRA_REMOVE_USER_DATA, false); |
3314 | Log.d(TAG, "doUninstallUbuntu"); |
3315 | |
3316 | @@ -476,7 +658,7 @@ |
3317 | |
3318 | // 1. force unmount |
3319 | // 2. restore android recovery partition, and deleted it. |
3320 | - // 3. delete system.img and SWAP.img. |
3321 | + // 3. delete system.img |
3322 | try { |
3323 | int r = executeSUCommands( |
3324 | new String[]{ |
3325 | @@ -492,67 +674,86 @@ |
3326 | Utils.getRecoveryPartitionPath()), |
3327 | (String.format("rm -f %s/%s || true\n", getFilesDir().toString(), ANDROID_REOCVERY_IMG)), |
3328 | ("rm -rf /data/system.img || true\n"), |
3329 | - ("rm -rf /data/SWAP.img || true\n"), |
3330 | } ); |
3331 | |
3332 | if (r == 0) { |
3333 | // delete installed version in preferences |
3334 | cleanUpdateCommand(); |
3335 | - VersionInfo.storeEmptyVersion( |
3336 | - getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE).edit(), PREF_KEY_INSTALLED_VERSION); |
3337 | + if (removeUserData) { |
3338 | + mSharedPreferences.edit() |
3339 | + .putInt( PREF_KEY_SIZE_SYSTEM_DATA, 0) |
3340 | + .putInt(PREF_KEY_SIZE_USER_DATA, 0) |
3341 | + .commit(); |
3342 | + } |
3343 | + setUbuntuUninstalled(); |
3344 | } |
3345 | - result.putExtra("result", r); |
3346 | } catch (EShellExecException e) { |
3347 | - result.putExtra("result", -1); |
3348 | + // ignore error |
3349 | } |
3350 | - |
3351 | - return result; |
3352 | } |
3353 | |
3354 | - private Intent doDeleteUbuntuUserData(Intent intent) { |
3355 | - Intent result = new Intent(VERSION_UPDATE); |
3356 | - File workingFolder = new File(mRootOfWorkPath, TEMP_FOLDER); |
3357 | + private void deleteUbuntuUserData() { |
3358 | + File workingFolder = new File(getFilesDir(), TEMP_FOLDER); |
3359 | File updateCommand = new File(workingFolder, UPDATE_COMMAND); |
3360 | |
3361 | try { |
3362 | - int r = executeSUCommands(new String[]{ |
3363 | - String.format("echo \"%s %s\" > %s\n", COMMAND_FORMAT, PARTITION_DATA, UPDATE_COMMAND), |
3364 | + mSharedPreferences.edit() |
3365 | + .putInt(PREF_KEY_SIZE_SYSTEM_DATA, 0) |
3366 | + .putInt(PREF_KEY_SIZE_USER_DATA, 0) |
3367 | + .commit(); |
3368 | + |
3369 | + executeSUCommands(new String[]{ |
3370 | + String.format("echo \"%s %s\" > %s\n", COMMAND_FORMAT, PARTITION_DATA, updateCommand.getAbsolutePath()), |
3371 | ("sh " + UPDATE_SCRIPT + " " + updateCommand.getAbsolutePath() + " " + getFilesDir().toString() + "\n") |
3372 | } ); |
3373 | - result.putExtra("result", r); |
3374 | } catch (EShellExecException e) { |
3375 | - result.putExtra("fail_description", e.getMessage()); |
3376 | - result.putExtra("result", -1); |
3377 | + Log.e(TAG,e.getMessage()); |
3378 | } |
3379 | - return result; |
3380 | } |
3381 | |
3382 | - private void doReboot(Intent intent) { |
3383 | - // Reboot to recovery to complete update, try power manager if we have permissions |
3384 | + private void rebootToUbuntu() { |
3385 | + // update storage use before reboot |
3386 | + doUpdateStorageUse(); |
3387 | try { |
3388 | - PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); |
3389 | - powerManager.reboot("recovery"); |
3390 | - } catch (SecurityException e) { |
3391 | - // FIXME: in Android 4.4, we do not get power manager permission. |
3392 | - // try it with SU permissions |
3393 | - try { |
3394 | - int r = executeSUCommands(new String[] { |
3395 | - String.format("%s -b %s/%s %s || true\n", |
3396 | - ANDROID_BOOTMGR, |
3397 | - getFilesDir().getAbsolutePath(), |
3398 | - UBUNTU_BOOT_IMG, |
3399 | - Utils.getRecoveryPartitionPath()), |
3400 | - "reboot recovery\n" |
3401 | - }); |
3402 | - if(r != 255) { |
3403 | - Utils.showToast(this.getApplicationContext(), "Rebooting to Ubuntu"); |
3404 | - } else { |
3405 | - Utils.showToast(this.getApplicationContext(), "No permissions to reboot to recovery"); |
3406 | - } |
3407 | - } catch (EShellExecException e1) { |
3408 | + int r = executeSUCommands(new String[] { |
3409 | + String.format("%s -b %s/%s %s || true\n", |
3410 | + ANDROID_BOOTMGR, |
3411 | + getFilesDir().getAbsolutePath(), |
3412 | + UBUNTU_BOOT_IMG, |
3413 | + Utils.getRecoveryPartitionPath()), |
3414 | + "reboot recovery\n" |
3415 | + }); |
3416 | + if(r != 255) { |
3417 | + Utils.showToast(this.getApplicationContext(), "Rebooting to Ubuntu"); |
3418 | + } else { |
3419 | Utils.showToast(this.getApplicationContext(), "No permissions to reboot to recovery"); |
3420 | } |
3421 | - } |
3422 | + } catch (EShellExecException e1) { |
3423 | + Utils.showToast(this.getApplicationContext(), "No permissions to reboot to recovery"); |
3424 | + } |
3425 | + } |
3426 | + |
3427 | + /** |
3428 | + * Install back original recovery image |
3429 | + */ |
3430 | + private void prepareAndroidUpdate() { |
3431 | + try { |
3432 | + int r = executeSUCommands(new String[] { |
3433 | + String.format("%s -b %s/%s %s || true\n", |
3434 | + ANDROID_BOOTMGR, |
3435 | + getFilesDir().getAbsolutePath(), |
3436 | + ANDROID_REOCVERY_IMG, |
3437 | + Utils.getRecoveryPartitionPath()) |
3438 | + }); |
3439 | + if(r != 255) { |
3440 | + Utils.showToast(this.getApplicationContext(), "Restoring original recovery for Android updates"); |
3441 | + } else { |
3442 | + Utils.showToast(this.getApplicationContext(), "No permissions to restore recovery"); |
3443 | + } |
3444 | + } catch (EShellExecException e1) { |
3445 | + Utils.showToast(this.getApplicationContext(), "No permissions to restore recovery"); |
3446 | + } |
3447 | + |
3448 | } |
3449 | |
3450 | /** |
3451 | @@ -563,16 +764,27 @@ |
3452 | * @throws EShellExecException |
3453 | */ |
3454 | private int executeSUCommands(String[] commands) throws EShellExecException { |
3455 | + mWakeLock.acquire(2 * 60 * 1000); // 2 minutes |
3456 | + try { |
3457 | + return doExecuteSUCommands(commands); |
3458 | + } finally { |
3459 | + if (mWakeLock.isHeld() ) { |
3460 | + mWakeLock.release(); |
3461 | + } |
3462 | + Log.d(TAG, "executeSUCommands-releasing wakelocks"); |
3463 | + } |
3464 | + } |
3465 | + |
3466 | + private int doExecuteSUCommands(String[] commands) throws EShellExecException { |
3467 | int ret = 0; |
3468 | - File rootFolder = new File(mRootOfWorkPath); |
3469 | - File workingFolder = new File(rootFolder, TEMP_FOLDER); |
3470 | + File workingFolder = new File(getFilesDir(), TEMP_FOLDER); |
3471 | String workingFolderPath = workingFolder.getAbsolutePath(); |
3472 | |
3473 | if (!workingFolder.exists() && !workingFolder.mkdir()) { |
3474 | throw(new EShellExecException("Failed to create working folder")); |
3475 | } |
3476 | |
3477 | - broadcastProgress(0, "Extracting supporting files at " + workingFolder.getAbsolutePath()); |
3478 | + broadcastProgress("Extracting supporting files at " + workingFolder.getAbsolutePath()); |
3479 | try { |
3480 | // extract utils into working folder. |
3481 | Utils.extractExecutableAsset(this, ANDROID_BOOTMGR, workingFolderPath, true); |
3482 | @@ -581,12 +793,10 @@ |
3483 | Utils.extractExecutableAsset(this, GPG, workingFolderPath, true); |
3484 | Utils.extractExecutableAsset(this, TAR, workingFolderPath, true); |
3485 | Utils.extractExecutableAsset(this, UPDATE_SCRIPT, workingFolderPath, true); |
3486 | - Utils.extractExecutableAsset(this, UPGRADECHECKER, workingFolderPath, true); |
3487 | } catch (IOException e) { |
3488 | throw(new EShellExecException("Failed to extract supporting utils")); |
3489 | } |
3490 | |
3491 | - mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "shelling"); |
3492 | try { |
3493 | Process process = Runtime.getRuntime().exec("su", null, workingFolder); |
3494 | DataOutputStream os = new DataOutputStream(process.getOutputStream()); |
3495 | @@ -615,6 +825,7 @@ |
3496 | InputStream es = process.getErrorStream(); |
3497 | boolean running = true; |
3498 | boolean scriptExecuted = false; |
3499 | + long time = System.currentTimeMillis(); |
3500 | do { |
3501 | while( is.available() > 0) { |
3502 | read = is.read(buff); |
3503 | @@ -623,30 +834,24 @@ |
3504 | } |
3505 | scriptExecuted = true; |
3506 | String seg = new String(buff, 0, read); |
3507 | - Log.i(TAG, "Script Output: " + seg); |
3508 | - broadcastProgress(-1, seg); |
3509 | + |
3510 | + Log.i(TAG, "Time(" + ((System.currentTimeMillis() - time)/1000) + "):Script Output: " + seg); |
3511 | + broadcastProgress(seg); |
3512 | + scanOutPut(seg); |
3513 | } |
3514 | while( es.available() > 0) { |
3515 | read = es.read(buff); |
3516 | if ( read <= 0 ) { |
3517 | break; |
3518 | } |
3519 | - scriptExecuted = true; |
3520 | - String seg = new String(buff,0,read); |
3521 | - |
3522 | - if (seg.startsWith("SWAP-file-missing")) { |
3523 | - // this is signal that we will also install swap, adjust progress estimates |
3524 | - mTotalSize += PROGRESS_MKSWAP_ADJUSTMENT + PROGRESS_SWAP_CREATION_ADJUSTMENT; |
3525 | - } else { |
3526 | - mProgress++; |
3527 | - if (mTotalSize > 0 && mLastSignalledProgress < (mProgress * 100 / mTotalSize)) { |
3528 | - // update and signal new progress |
3529 | - mLastSignalledProgress = (int) (mProgress * 100 / mTotalSize); |
3530 | - broadcastProgress(mLastSignalledProgress, null); |
3531 | - } |
3532 | + scriptExecuted = true; |
3533 | + mProgress++; |
3534 | + if (mTotalSize > 0 && mLastSignalledProgress < (mProgress * 100 / mTotalSize)) { |
3535 | + // update and signal new progress |
3536 | + mLastSignalledProgress = (int) (mProgress * 100 / mTotalSize); |
3537 | + broadcastProgress(null); |
3538 | } |
3539 | - |
3540 | - Log.i(TAG, "Stderr Output: " + seg); |
3541 | + // Log.i(TAG, "Stderr Output: " + new String(buff,0,read)); |
3542 | } |
3543 | try { |
3544 | ret = process.exitValue(); |
3545 | @@ -663,335 +868,467 @@ |
3546 | } while (running); |
3547 | } catch (IOException e) { |
3548 | throw(new EShellExecException("Script execution exception " + e.getMessage())); |
3549 | + } |
3550 | + Log.d(TAG, "executeSUCommands-done"); |
3551 | + return ret; |
3552 | + } |
3553 | + |
3554 | + /** |
3555 | + * Scan output stream for additional information about installed system |
3556 | + * It scans for: |
3557 | + * - usage data statistics |
3558 | + * - installed version information |
3559 | + * - update channel url if needed |
3560 | + * |
3561 | + * @param seg |
3562 | + */ |
3563 | + private void scanOutPut(String seg) { |
3564 | + for( String line : seg.split("\n")) { |
3565 | + if (line.endsWith(UBUNTU_ROOTFS)) { |
3566 | + storeStorageUse(line, PREF_KEY_SIZE_ROOTFS); |
3567 | + } else if (line.endsWith(UBUNTU_SYSTEM_DATA)) { |
3568 | + storeStorageUse(line, PREF_KEY_SIZE_SYSTEM_DATA); |
3569 | + } else if (line.endsWith(UBUNTU_USER_DATA)) { |
3570 | + storeStorageUse(line, PREF_KEY_SIZE_USER_DATA); |
3571 | + } else if (line.startsWith("build_number:")) { |
3572 | + parseVersion(line, PREF_KEY_VERSION_NUMBER); |
3573 | + } else if (line.startsWith("channel:")) { |
3574 | + parseVersion(line, PREF_KEY_VERSION_CHANNEL); |
3575 | + } else if (line.startsWith("channel_target:")) { |
3576 | + parseVersion(line, PREF_KEY_VERSION_CHANNEL_TARGET); |
3577 | + } else if (line.startsWith("version_detail:")) { |
3578 | + parseVersion(line, PREF_KEY_VERSION_DESCRIPTION); |
3579 | + } else if (line.startsWith("base:")) { |
3580 | + parseVersion(line, PREF_KEY_VERSION_BASE); |
3581 | + } |
3582 | + } |
3583 | + } |
3584 | + |
3585 | + /** |
3586 | + * if channel address is empty, try to reconstruct it from version info |
3587 | + */ |
3588 | + private void checkChannelAddress() { |
3589 | + if (!mSharedPreferences.contains(PREF_KEY_DOWNLOAD_CHANNEL) |
3590 | + || !mSharedPreferences.contains(PREF_KEY_DOWNLOAD_SERVER)){ |
3591 | + final String base = mSharedPreferences.getString(PREF_KEY_VERSION_BASE, ""); |
3592 | + String channel = mSharedPreferences.getString(PREF_KEY_VERSION_CHANNEL, ""); |
3593 | + // if we have network, try to ping server, otherwise guess |
3594 | + String channelUrl = null; |
3595 | + if (isNetworkAvailable()) { |
3596 | + channelUrl = doGetChannels(String.format("http://%s", base), false, true, true, true).get(channel); |
3597 | + } |
3598 | + |
3599 | + if (channelUrl == null) { |
3600 | + // guess name |
3601 | + if (channel.contains("ubuntu-touch/")) { |
3602 | + channelUrl = String.format("%s/%s/index.json", channel, Utils.getDeviceModel()); |
3603 | + } else { |
3604 | + channelUrl = String.format("ubuntu-touch/%s/%s/index.json", channel, Utils.getDeviceModel()); |
3605 | + } |
3606 | + } |
3607 | + Log.d(TAG, "Constructed channel url:" + base + "/" + channelUrl); |
3608 | + mSharedPreferences.edit() |
3609 | + .putString(PREF_KEY_DOWNLOAD_CHANNEL, channelUrl) |
3610 | + .putString(PREF_KEY_DOWNLOAD_SERVER, String.format("http://%s", base)) |
3611 | + .commit(); |
3612 | + } |
3613 | + } |
3614 | + |
3615 | + private void storeStorageUse(String value, String key) { |
3616 | + final String[] spl = value.split("\t"); |
3617 | + if (spl.length != 0) { |
3618 | + final int size = Integer.valueOf(spl[0]); |
3619 | + mSharedPreferences.edit().putInt(key, size).commit(); |
3620 | + final Intent notification = new Intent(STORAGE_USE_UPDATED); |
3621 | + sendBroadcast(notification); |
3622 | + } |
3623 | + } |
3624 | + |
3625 | + private void parseVersion(String value, String key) { |
3626 | + final String[] spl = value.split(": "); |
3627 | + if (spl.length >= 2) { |
3628 | + mSharedPreferences.edit().putString(key, spl[1]).commit(); |
3629 | + } |
3630 | + } |
3631 | + |
3632 | + private Intent downloadRelease(Intent intent) { |
3633 | + String channel = intent.getStringExtra(DOWNLOAD_RELEASE_EXTRA_CHANNEL_URL); |
3634 | + String serverUrl = intent.getStringExtra(DOWNLOAD_RELEASE_EXTRA_SERVER_URL); |
3635 | + boolean bootstrap = intent.getBooleanExtra(DOWNLOAD_RELEASE_EXTRA_BOOTSTRAP,true); // default bootstrap on |
3636 | + int version = intent.getIntExtra(DOWNLOAD_RELEASE_EXTRA_VERSION, -1); |
3637 | + ReleaseType releaseType = ReleaseType.fromValue( |
3638 | + intent.getIntExtra(DOWNLOAD_RELEASE_EXTRA_TYPE, ReleaseType.FULL.getValue())); // by default look for full releases |
3639 | + // First delete old release if it exists |
3640 | + doDeleteDownloadedRelease(); |
3641 | + mSharedPreferences.edit(). |
3642 | + putString(PREF_KEY_DOWNLOAD_SERVER, serverUrl). |
3643 | + putString(PREF_KEY_DOWNLOAD_CHANNEL, channel). |
3644 | + commit(); |
3645 | + return downloadAllPackages(bootstrap, version, releaseType); |
3646 | + } |
3647 | + |
3648 | + /** |
3649 | + * Download first available download |
3650 | + */ |
3651 | + private Intent downloadUpdate() { |
3652 | + // -1 will pick update available for this release |
3653 | + return downloadAllPackages(false, -1, ReleaseType.DELTA); |
3654 | + } |
3655 | + |
3656 | + private Intent resumeDownload() { |
3657 | + boolean bootstrap = mSharedPreferences.getBoolean(PREF_KEY_DOWNLOAD_BOOTSTRAP, false); |
3658 | + int version = mSharedPreferences.getInt(PREF_KEY_DOWNLOAD_VERSION, -1); |
3659 | + ReleaseType releaseType = ReleaseType.fromValue( |
3660 | + mSharedPreferences.getInt(PREF_KEY_DOWNLOAD_TYPE, ReleaseType.FULL.getValue())); |
3661 | + return downloadAllPackages(bootstrap, version, releaseType); |
3662 | + } |
3663 | + |
3664 | + @SuppressLint("Wakelock") |
3665 | + private Intent downloadAllPackages(boolean bootstrap, int version, ReleaseType releaseType ) { |
3666 | + mWakeLock.acquire(); |
3667 | + mWifiLock.acquire(); |
3668 | + try { |
3669 | + return doDownloadAllPackages( bootstrap, version, releaseType); |
3670 | } finally { |
3671 | - if (mWakeLock != null && mWakeLock.isHeld()) { |
3672 | + Log.d(TAG, "downloadAllPackages-releasing wakelocks"); |
3673 | + if (mWakeLock.isHeld() ) { |
3674 | mWakeLock.release(); |
3675 | } |
3676 | + if (mWifiLock.isHeld()) { |
3677 | + mWifiLock.release(); |
3678 | + } |
3679 | } |
3680 | - return ret; |
3681 | } |
3682 | - |
3683 | - private Intent doDownloadRelease(Intent intent) { |
3684 | - mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ufa-downloading"); |
3685 | + @SuppressLint("CommitPrefEdits") |
3686 | + private Intent doDownloadAllPackages(boolean bootstrap, int version, ReleaseType releaseType ) { |
3687 | mIsCanceled = false; |
3688 | - SharedPreferences.Editor editor = getSharedPreferences( SHARED_PREF, Context.MODE_PRIVATE).edit(); |
3689 | - |
3690 | + dismissUbuntuNotification(); |
3691 | + mActionOutput = ""; |
3692 | + broadcastProgress(getString(R.string.downloading_starting)); |
3693 | + String channel = mSharedPreferences.getString(PREF_KEY_DOWNLOAD_CHANNEL, null); |
3694 | + String serverUrl = mSharedPreferences.getString(PREF_KEY_DOWNLOAD_SERVER, null); |
3695 | Intent result = new Intent(DOWNLOAD_RESULT); |
3696 | - VersionInfo prevDownload = getDownloadVersion(this.getApplicationContext()); |
3697 | - try { |
3698 | - File rootFolder = new File(mRootOfWorkPath); |
3699 | - |
3700 | - // first get from JSON list of files to download |
3701 | - String alias = intent.getStringExtra(DOWNLOAD_RELEASE_EXTRA_CHANNEL_ALIAS); |
3702 | - String jsonUrl = intent.getStringExtra(DOWNLOAD_RELEASE_EXTRA_CHANNEL_URL); |
3703 | - boolean bootstrap = intent.getBooleanExtra(DOWNLOAD_RELEASE_EXTRA_BOOTSTRAP,true); // default bootstrap on |
3704 | - int version = intent.getIntExtra(DOWNLOAD_RELEASE_EXTRA_VERSION, -1); |
3705 | - ReleaseType releaseType = ReleaseType.fromValue( |
3706 | - intent.getIntExtra(DOWNLOAD_RELEASE_EXTRA_TYPE, ReleaseType.FULL.getValue())); // by default look for full releases |
3707 | - |
3708 | - String jsonStr = Utils.httpDownload(BASE_URL + jsonUrl); |
3709 | - List<Image> releases = JsonChannelParser.getAvailableReleases(jsonStr, ReleaseType.FULL); |
3710 | - if (releases.size() == 0 || releases.get(0).files.length == 0 ) { |
3711 | - // something is wrong, empty release |
3712 | - Log.e(TAG, "Empty releas"); |
3713 | - return handleDownloadError(result, -1, "Empty release"); |
3714 | + if (channel == null || serverUrl == null) { |
3715 | + doDeleteDownloadedRelease(); |
3716 | + return handleDownloadError(result, -1, "Missing update server or channel url"); |
3717 | + } |
3718 | + |
3719 | + String jsonStr = Utils.httpDownload(String.format("%s/%s", serverUrl, channel)); |
3720 | + if (jsonStr == null) { |
3721 | + Log.e(TAG, "Failed to fetch channel content"); |
3722 | + return handleDownloadError(result, -1, "Failed to fetch channel content, check url"); |
3723 | + } |
3724 | + List<Image> releases = JsonChannelParser.getAvailableReleases(jsonStr, releaseType); |
3725 | + if (releases.size() == 0 || releases.get(0).files.length == 0 ) { |
3726 | + // something is wrong, empty release |
3727 | + Log.e(TAG, "Empty releas"); |
3728 | + return handleDownloadError(result, -1, "Empty release"); |
3729 | + } |
3730 | + // get right version, otherwise first since that is most recent one |
3731 | + Image choosenRelease = null; |
3732 | + if (version != -1) { |
3733 | + // look for given release |
3734 | + for (Image i : releases) { |
3735 | + if (i.version == version) { |
3736 | + choosenRelease = i; |
3737 | + break; |
3738 | + } |
3739 | } |
3740 | - // get right version, otherwise first since that is most recent one |
3741 | - Image choosenRelease = null; |
3742 | - if (version != -1) { |
3743 | - // look for given release |
3744 | - for (Image i : releases) { |
3745 | - if (i.version == version) { |
3746 | + } else { |
3747 | + if (releaseType == ReleaseType.FULL) { |
3748 | + choosenRelease = releases.get(0); |
3749 | + } else { |
3750 | + // this is update, found release wich relates to installed one |
3751 | + String baseStr = mSharedPreferences.getString(PREF_KEY_VERSION_NUMBER, "0"); |
3752 | + int base = Integer.valueOf(baseStr); |
3753 | + for(Image i : releases) { |
3754 | + if (i.base == base) { |
3755 | choosenRelease = i; |
3756 | break; |
3757 | } |
3758 | } |
3759 | - if (choosenRelease == null) { |
3760 | - Log.e(TAG, "wrong release vwersion"); |
3761 | - return handleDownloadError(result, -1, "wrong release vwersion"); |
3762 | + } |
3763 | + } |
3764 | + if (choosenRelease == null) { |
3765 | + Log.e(TAG, "wrong release vwersion"); |
3766 | + return handleDownloadError(result, -1, "wrong release version"); |
3767 | + } |
3768 | + |
3769 | + JsonChannelParser.File updateFiles[] = choosenRelease.files; |
3770 | + // sort update files |
3771 | + List<JsonChannelParser.File> filesArray = new LinkedList<JsonChannelParser.File>(); |
3772 | + for(JsonChannelParser.File f: updateFiles) { |
3773 | + // In bring up mode, skip device package updates |
3774 | + if (mBringup) { |
3775 | + if (!f.path.contains("device-")){ |
3776 | + filesArray.add(f); |
3777 | } |
3778 | } else { |
3779 | - choosenRelease = releases.get(0); |
3780 | - } |
3781 | - JsonChannelParser.File updateFiles[] = choosenRelease.files; |
3782 | - // sort update files |
3783 | - List<JsonChannelParser.File> filesArray = new LinkedList<JsonChannelParser.File>(); |
3784 | - for(JsonChannelParser.File f: updateFiles) { |
3785 | filesArray.add(f); |
3786 | } |
3787 | - Collections.sort(filesArray, JsonChannelParser.fileComparator()); |
3788 | - String updateFilenames[] = new String[updateFiles.length * 2]; |
3789 | - |
3790 | - // get list of keyrings to download |
3791 | - String keyrings[] = { |
3792 | - String.format("%s/%s",BASE_URL, URL_IMAGE_MASTER), |
3793 | - String.format("%s/%s",BASE_URL, URL_IMAGE_SIGNING), |
3794 | - }; |
3795 | - String keyringsFilenames[] = new String[keyrings.length * 2]; |
3796 | - |
3797 | - // First delete old release if it exists |
3798 | - { |
3799 | - boolean toDeleteOld = true; |
3800 | - if (prevDownload != null) { |
3801 | - if (prevDownload.equals(jsonUrl, choosenRelease.version, releaseType) && |
3802 | - prevDownload.mDownloadedSize > 0) { |
3803 | - toDeleteOld = false; |
3804 | - } |
3805 | - } |
3806 | - if (toDeleteOld) { |
3807 | - String s = deleteRelease(); |
3808 | - if (s != null) { |
3809 | - // remove failed |
3810 | - return handleDownloadError(result, -1, s); |
3811 | - } |
3812 | - } |
3813 | - } |
3814 | - |
3815 | - // make sure release folder exists |
3816 | - File release = new File(rootFolder, RELEASE_FOLDER); |
3817 | - release.mkdir(); |
3818 | - // download release |
3819 | - long time = System.currentTimeMillis(); |
3820 | - mLastSignalledProgress = 0; |
3821 | - mProgress = 0; |
3822 | - broadcastProgress(mLastSignalledProgress, null); |
3823 | - mTotalSize = Utils.calculateDownloadSize(filesArray); |
3824 | - long neededSize = mTotalSize; |
3825 | - if (prevDownload != null) { |
3826 | - neededSize = mTotalSize - prevDownload.mDownloadedSize; |
3827 | - } |
3828 | - boolean isStorageEnough = isStorageSpaceEnoughBFDownload(neededSize); |
3829 | - if (! isStorageEnough) { |
3830 | - String msg = "Need more storage: "; |
3831 | - if (workPathInCache) { |
3832 | - msg += "/cache need " + String.valueOf(mTotalSize) + " bytes for download and /data need 2.5G for system"; |
3833 | + } |
3834 | + Collections.sort(filesArray, JsonChannelParser.fileComparator()); |
3835 | + String updateFilenames[] = new String[updateFiles.length]; |
3836 | + |
3837 | + // make sure release folder exists |
3838 | + mReleaseFolder.mkdir(); |
3839 | + // download release |
3840 | + long time = System.currentTimeMillis(); |
3841 | + mLastSignalledProgress = 0; |
3842 | + mProgress = 0; |
3843 | + broadcastProgress(null); |
3844 | + mTotalSize = Utils.calculateDownloadSize(filesArray); |
3845 | + long neededSize = mTotalSize; |
3846 | + boolean resuming = mSharedPreferences.getBoolean(PREF_KEY_DOWNLOAD_ACTIVE, false); |
3847 | + if (resuming ) { |
3848 | + neededSize = mTotalSize - mSharedPreferences.getLong(PREF_KEY_DOWNLOAD_COMPLETED, 0); |
3849 | + } |
3850 | + boolean isStorageEnough = isStorageSpaceEnoughBFDownload(neededSize); |
3851 | + if (! isStorageEnough) { |
3852 | + String msg = "Need more storage: "; |
3853 | + msg += "/data need 2.5G for system plus " + String.valueOf(mTotalSize) + " bytes for download"; |
3854 | + Log.i(TAG, msg); |
3855 | + return handleDownloadError(result, -1, msg); |
3856 | + } |
3857 | + |
3858 | + // Store download info |
3859 | + mSharedPreferences.edit() |
3860 | + .putBoolean(PREF_KEY_DOWNLOAD_BOOTSTRAP, bootstrap) |
3861 | + .putInt(PREF_KEY_DOWNLOAD_VERSION, version) |
3862 | + .putInt(PREF_KEY_DOWNLOAD_TYPE, releaseType.getValue()) |
3863 | + .putBoolean(PREF_KEY_DOWNLOAD_ACTIVE, true) |
3864 | + .putString(PREF_KEY_DOWNLOAD_SERVER, serverUrl) |
3865 | + .putString(PREF_KEY_DOWNLOAD_CHANNEL, channel) |
3866 | + .commit(); |
3867 | + |
3868 | + // mProgressSteps = mTotalDownloadSize / 100; // we want 1% steps |
3869 | + long downloadedSize = 0; |
3870 | + JsonChannelParser.File currentDownloadingFile = null; |
3871 | + try { |
3872 | + int i = 0; |
3873 | + // download all update packages |
3874 | + i = 0; |
3875 | + for (JsonChannelParser.File file : filesArray){ |
3876 | + URL url = new URL(serverUrl + file.path); |
3877 | + String fileName = URLUtil.guessFileName(url.toString(), null, null); |
3878 | + File f = new File(mReleaseFolder, fileName); |
3879 | + |
3880 | + boolean fileNeedDownload = true; |
3881 | + if (resuming) { |
3882 | + long length = f.length(); |
3883 | + if (length == file.size) { |
3884 | + fileNeedDownload = false; |
3885 | + } else if (length > file.size) { |
3886 | + f.delete(); |
3887 | + } |
3888 | + } |
3889 | + if (fileNeedDownload) { |
3890 | + currentDownloadingFile = file; |
3891 | + updateFilenames[i] = doDownloadFile(serverUrl, file, mReleaseFolder); |
3892 | + currentDownloadingFile = null; |
3893 | } else { |
3894 | - msg += "/data need 2.5G for system plus " + String.valueOf(mTotalSize) + " bytes for download"; |
3895 | - } |
3896 | - Log.i(TAG, msg); |
3897 | - return handleDownloadError(result, -1, msg); |
3898 | - } |
3899 | - |
3900 | - // mProgressSteps = mTotalDownloadSize / 100; // we want 1% steps |
3901 | - long downloadedSize = 0; |
3902 | - JsonChannelParser.File currentDownloadingFile = null; |
3903 | + updateFilenames[i] = fileName; |
3904 | + mProgress += file.size; |
3905 | + mLastSignalledProgress = (int) (mProgress * 100 / mTotalSize); |
3906 | + broadcastProgress(null); |
3907 | + } |
3908 | + |
3909 | + // check file size and check sum |
3910 | + long length = f.length(); |
3911 | + if (length != file.size) { |
3912 | + f.delete(); |
3913 | + throw new ESumNotMatchException(); |
3914 | + } |
3915 | + broadcastProgress("Checksum Verifying: " + fileName); |
3916 | + String sha256sum = Utils.getSha256Sum(f); |
3917 | + if (! sha256sum.equals(file.checksum)) { |
3918 | + broadcastProgress("Checksum Verify failed: " + fileName); |
3919 | + f.delete(); |
3920 | + throw new ESumNotMatchException(); |
3921 | + } |
3922 | + broadcastProgress("Checksum Verified: " + fileName); |
3923 | + downloadedSize += file.size; |
3924 | + i++; |
3925 | + } |
3926 | + |
3927 | + // data required for installation. |
3928 | + // Ubuntu reboot apps. |
3929 | + Utils.extractExecutableAsset(this, U_REBOOT_APP, mReleaseFolder.getAbsolutePath(), false); |
3930 | + Utils.extractExecutableAsset(this, RECOVERY_REMOUNT, mReleaseFolder.getAbsolutePath(), false); |
3931 | + } catch (MalformedURLException e) { |
3932 | + Log.e(TAG, "Failed to download release:", e); |
3933 | + return handleDownloadError(result, -1, "Malformed release url"); |
3934 | + } catch (FileNotFoundException e) { |
3935 | + Log.e(TAG, "Failed to download release:", e); |
3936 | + return handleDownloadError(result, -1, "File not found"); |
3937 | + } catch (IOException e){ |
3938 | + if (currentDownloadingFile != null) { |
3939 | + try { |
3940 | + URL url = new URL(serverUrl + currentDownloadingFile.path); |
3941 | + String fileName = URLUtil.guessFileName(url.toString(), null, null); |
3942 | + File f = new File(mReleaseFolder, fileName); |
3943 | + downloadedSize += f.length(); |
3944 | + } catch (MalformedURLException e1) { |
3945 | + // shouldn't happen for it should already happen. |
3946 | + } |
3947 | + } |
3948 | + |
3949 | + if (downloadedSize == 0) { |
3950 | + doDeleteDownloadedRelease(); |
3951 | + mSharedPreferences.edit().putBoolean(PREF_KEY_DOWNLOAD_ACTIVE, false).commit(); |
3952 | + } else { |
3953 | + mSharedPreferences.edit().putLong(PREF_KEY_DOWNLOAD_COMPLETED, downloadedSize).commit(); |
3954 | + } |
3955 | + |
3956 | + Log.e(TAG, "Failed to download release:", e); |
3957 | + return handleDownloadError(result, -1, "IO Error"); |
3958 | + } catch (ESumNotMatchException e) { |
3959 | + // Download file check sum error !! |
3960 | + doDeleteDownloadedRelease(); |
3961 | + return handleDownloadError(result, -1, "Download check sum error"); |
3962 | + } catch (ECancelException e) { |
3963 | + // Download was cancelled by user |
3964 | + downloadedSize += e.mDownloadedSize; |
3965 | + if (downloadedSize == 0) { |
3966 | + mSharedPreferences.edit().putBoolean(PREF_KEY_DOWNLOAD_ACTIVE, false).commit(); |
3967 | + } else { |
3968 | + mSharedPreferences.edit().putLong(PREF_KEY_DOWNLOAD_COMPLETED, downloadedSize).commit(); |
3969 | + } |
3970 | + |
3971 | + return handleDownloadError(result, -2, "Download cancelled by user"); |
3972 | + } |
3973 | + |
3974 | + Log.i(TAG, "Download done in " + (System.currentTimeMillis() - time )/1000 + " seconds"); |
3975 | + broadcastProgress("Generating update command"); |
3976 | + |
3977 | + // generate update_command |
3978 | + File updateCommand = new File(mReleaseFolder, UPDATE_COMMAND); |
3979 | + try { |
3980 | + FileOutputStream fos = new FileOutputStream(updateCommand); |
3981 | try { |
3982 | + if (bootstrap) { |
3983 | + fos.write((String.format("%s %s\n", COMMAND_FORMAT, PARTITION_DATA)).getBytes()); |
3984 | + } |
3985 | + if (releaseType == ReleaseType.FULL) { |
3986 | + fos.write((String.format("%s %s\n", COMMAND_FORMAT, PARTITION_SYSTEM)).getBytes()); |
3987 | + } |
3988 | + fos.write((String.format("%s %s\n", COMMAND_MOUNT, PARTITION_SYSTEM)).getBytes()); |
3989 | + |
3990 | + // add update commands |
3991 | int i = 0; |
3992 | - for(String url : keyrings){ |
3993 | - keyringsFilenames[i++] = doDownloadUrl(new URL(url), release); |
3994 | - // download signature |
3995 | - keyringsFilenames[i++] = doDownloadUrl(new URL(url+ASC_SUFFIX), release); |
3996 | - } |
3997 | - |
3998 | - // download all update images |
3999 | - i = 0; |
4000 | - for (JsonChannelParser.File file : filesArray){ |
4001 | - URL url = new URL(BASE_URL + file.path); |
4002 | - String fileName = URLUtil.guessFileName(url.toString(), null, null); |
4003 | - File f = new File(release, fileName); |
4004 | - |
4005 | - boolean fileNeedDownload = true; |
4006 | - if (prevDownload != null) { |
4007 | - long length = f.length(); |
4008 | - if (length == file.size) { |
4009 | - fileNeedDownload = false; |
4010 | - } else if (length > file.size) { |
4011 | - f.delete(); |
4012 | - } |
4013 | - } |
4014 | - if (fileNeedDownload) { |
4015 | - currentDownloadingFile = file; |
4016 | - updateFilenames[i] = doDownloadFile(file, release); |
4017 | - currentDownloadingFile = null; |
4018 | - } else { |
4019 | - updateFilenames[i] = fileName; |
4020 | - mProgress += file.size; |
4021 | - mLastSignalledProgress = (int) (mProgress * 100 / mTotalSize); |
4022 | - broadcastProgress(mLastSignalledProgress, null); |
4023 | - } |
4024 | - |
4025 | - // check file size and check sum |
4026 | - long length = f.length(); |
4027 | - if (length != file.size) { |
4028 | - f.delete(); |
4029 | - throw new ESumNotMatchException(); |
4030 | - } |
4031 | - broadcastProgress(mLastSignalledProgress, "Checksum Verifying: " + fileName); |
4032 | - String sha256sum = Utils.getSha256Sum(f); |
4033 | - if (! sha256sum.equals(file.checksum)) { |
4034 | - broadcastProgress(mLastSignalledProgress, "Checksum Verify failed: " + fileName); |
4035 | - f.delete(); |
4036 | - throw new ESumNotMatchException(); |
4037 | - } |
4038 | - broadcastProgress(mLastSignalledProgress, "Checksum Verified: " + fileName); |
4039 | - downloadedSize += file.size; |
4040 | - i++; |
4041 | - |
4042 | - // signature file size is not accounted for resume since it's quite small |
4043 | - updateFilenames[i] = doDownloadFileSignature(file, release); |
4044 | - i++; |
4045 | - } |
4046 | - |
4047 | - // data required for installation. |
4048 | - Utils.extractExecutableAsset(this, ARCHIVE_MASTER_ASC, release.getAbsolutePath(), false); |
4049 | - Utils.extractExecutableAsset(this, ARCHIVE_MASTER, release.getAbsolutePath(), false); |
4050 | - // Ubuntu reboot apps. |
4051 | - Utils.extractExecutableAsset(this, U_REBOOT_APP_ASC, release.getAbsolutePath(), false); |
4052 | - Utils.extractExecutableAsset(this, U_REBOOT_APP, release.getAbsolutePath(), false); |
4053 | - } catch (MalformedURLException e) { |
4054 | - Log.e(TAG, "Failed to download release:", e); |
4055 | - return handleDownloadError(result, -1, "Malformed release url"); |
4056 | - } catch (FileNotFoundException e) { |
4057 | - Log.e(TAG, "Failed to download release:", e); |
4058 | - return handleDownloadError(result, -1, "File not found"); |
4059 | - } catch (IOException e){ |
4060 | - if (currentDownloadingFile != null) { |
4061 | - try { |
4062 | - URL url = new URL(BASE_URL + currentDownloadingFile.path); |
4063 | - String fileName = URLUtil.guessFileName(url.toString(), null, null); |
4064 | - File f = new File(release, fileName); |
4065 | - downloadedSize += f.length(); |
4066 | - } catch (MalformedURLException e1) { |
4067 | - // shouldn't happen for it should already happen. |
4068 | - } |
4069 | - } |
4070 | - |
4071 | - if (downloadedSize > 0) { |
4072 | - VersionInfo v = new VersionInfo(alias, jsonUrl, choosenRelease.description, choosenRelease.version, |
4073 | - downloadedSize, releaseType); |
4074 | - v.storeVersion(editor, PREF_KEY_DOWNLOADED_VERSION); |
4075 | - } else { |
4076 | - editor.putString(PREF_KEY_UPDATE_COMMAND, ""); |
4077 | - VersionInfo.storeEmptyVersion(editor, PREF_KEY_DOWNLOADED_VERSION); |
4078 | - } |
4079 | - |
4080 | - Log.e(TAG, "Failed to download release:", e); |
4081 | - return handleDownloadError(result, -1, "IO Error"); |
4082 | - } catch (ESumNotMatchException e) { |
4083 | - // Download file check sum error !! |
4084 | - return handleDownloadError(result, -1, "Download check sum error"); |
4085 | - } catch (ECancelException e) { |
4086 | - // Download was cancelled by user |
4087 | - downloadedSize += e.mDownloadedSize; |
4088 | - if (downloadedSize > 0) { |
4089 | - VersionInfo v = new VersionInfo(alias, jsonUrl, choosenRelease.description, choosenRelease.version, |
4090 | - downloadedSize, releaseType); |
4091 | - v.storeVersion(editor, PREF_KEY_DOWNLOADED_VERSION); |
4092 | - } |
4093 | - return handleDownloadError(result, -2, "Download cancelled by user"); |
4094 | - } |
4095 | - |
4096 | - Log.i(TAG, "Download done in " + (System.currentTimeMillis() - time )/1000 + " seconds"); |
4097 | - broadcastProgress(-1, "Generating update command"); |
4098 | - |
4099 | - // generate update_command |
4100 | - File updateCommand = new File(release, UPDATE_COMMAND); |
4101 | - try { |
4102 | - FileOutputStream fos = new FileOutputStream(updateCommand); |
4103 | - try { |
4104 | - if (bootstrap) { |
4105 | - fos.write((String.format("%s %s\n", COMMAND_FORMAT, PARTITION_DATA)).getBytes()); |
4106 | - } |
4107 | - if (releaseType == ReleaseType.FULL) { |
4108 | - fos.write((String.format("%s %s\n", COMMAND_FORMAT, PARTITION_SYSTEM)).getBytes()); |
4109 | - } |
4110 | - // load keyrings |
4111 | - int i = 0; |
4112 | - while (i < keyringsFilenames.length) { |
4113 | - fos.write((String.format("%s %s %s\n", |
4114 | - COMMAND_LOAD_KEYRING, |
4115 | - keyringsFilenames[i++], |
4116 | - keyringsFilenames[i++])).getBytes()); |
4117 | - } |
4118 | - fos.write((String.format("%s %s\n", COMMAND_MOUNT, PARTITION_SYSTEM)).getBytes()); |
4119 | - |
4120 | - // add update commands |
4121 | - i = 0; |
4122 | - while (i < updateFilenames.length) { |
4123 | - fos.write((String.format("%s %s %s\n", |
4124 | - COMMAND_UPDATE, |
4125 | - updateFilenames[i++], |
4126 | - updateFilenames[i++])).getBytes()); |
4127 | - } |
4128 | - |
4129 | - // add Ubuntu reboot app update package |
4130 | - if (releaseType == ReleaseType.FULL) { |
4131 | - fos.write((String.format("%s %s %s\n", |
4132 | - COMMAND_UPDATE, |
4133 | - U_REBOOT_APP, |
4134 | - U_REBOOT_APP_ASC)).getBytes()); |
4135 | - } |
4136 | - if(releaseType == ReleaseType.DELTA) { |
4137 | - // TODO: |
4138 | - } |
4139 | - fos.write((String.format("%s %s\n", COMMAND_UMOUNT, PARTITION_SYSTEM)).getBytes()); |
4140 | - fos.flush(); |
4141 | - } finally { |
4142 | - fos.close(); |
4143 | - } |
4144 | - } catch (IOException e) { |
4145 | - e.printStackTrace(); |
4146 | - return handleDownloadError(result, -1, "Failed to generate update command"); |
4147 | - } |
4148 | - broadcastProgress(-1, "Download done in " + (System.currentTimeMillis() - time )/1000 + " seconds"); |
4149 | - int estimatedCheckCount = 0; |
4150 | - for (JsonChannelParser.File file : filesArray){ |
4151 | - if (file.path.contains("ubuntu-")) { |
4152 | - estimatedCheckCount += (file.size / PROGRESS_UBUNTU_ADJUSTMENT); |
4153 | - } else if (file.path.contains("device-")) { |
4154 | - estimatedCheckCount += (file.size / PROGRESS_DEVICE_ADJUSTMENT); |
4155 | - } else if (file.path.contains("custom-")) { |
4156 | - estimatedCheckCount += (file.size / PROGRESS_CUSTOM_ADJUSTMENT); |
4157 | - } |
4158 | - } |
4159 | - // store update command |
4160 | - setUpdateCommand(updateCommand.getAbsolutePath()); |
4161 | - |
4162 | - // updated downloaded information. |
4163 | - VersionInfo v = new VersionInfo(alias, jsonUrl, choosenRelease.description, choosenRelease.version, 0, releaseType); |
4164 | - |
4165 | - editor.putInt(PREF_KEY_ESTIMATED_CHECKPOINTS, estimatedCheckCount); |
4166 | - v.storeVersion(editor, PREF_KEY_DOWNLOADED_VERSION); |
4167 | - mProgress = 100; |
4168 | - } finally { |
4169 | - if (mWakeLock != null && mWakeLock.isHeld()) { |
4170 | - mWakeLock.release(); |
4171 | - } |
4172 | + while (i < updateFilenames.length) { |
4173 | + fos.write((String.format("%s %s\n", |
4174 | + COMMAND_UPDATE, |
4175 | + updateFilenames[i++])).getBytes()); |
4176 | + } |
4177 | + |
4178 | + // add Ubuntu reboot app and recovery remount update packages |
4179 | + if (releaseType == ReleaseType.FULL) { |
4180 | + fos.write((String.format("%s %s\n", |
4181 | + COMMAND_UPDATE, |
4182 | + U_REBOOT_APP)).getBytes()); |
4183 | + |
4184 | + fos.write((String.format("%s %s\n", |
4185 | + COMMAND_UPDATE, |
4186 | + RECOVERY_REMOUNT)).getBytes()); |
4187 | + } |
4188 | + fos.write((String.format("%s %s\n", COMMAND_UMOUNT, PARTITION_SYSTEM)).getBytes()); |
4189 | + fos.flush(); |
4190 | + } finally { |
4191 | + fos.close(); |
4192 | + } |
4193 | + } catch (IOException e) { |
4194 | + e.printStackTrace(); |
4195 | + doDeleteDownloadedRelease(); |
4196 | + mSharedPreferences.edit().putBoolean(PREF_KEY_DOWNLOAD_ACTIVE, false).commit(); |
4197 | + return handleDownloadError(result, -1, "Failed to generate update command"); |
4198 | + } |
4199 | + |
4200 | + mLastSignalledProgress = 100; |
4201 | + broadcastProgress("Download done in " + (System.currentTimeMillis() - time )/1000 + " seconds"); |
4202 | + // store update command |
4203 | + setUpdateCommand(updateCommand.getAbsolutePath()); |
4204 | + mSharedPreferences.edit().putBoolean(PREF_KEY_DOWNLOAD_ACTIVE, false).commit(); |
4205 | + dismissProgressNotification(); |
4206 | + // check if we should also do install |
4207 | + if ( MIN_INSTALL_BATTERY_CHARGE < getBatteryCharge(this)) { |
4208 | + updateInstallerState(InstallerState.INSTALLING); |
4209 | + return doInstallUbuntu(); |
4210 | } |
4211 | result.putExtra(DOWNLOAD_RESULT_EXTRA_INT, 0); |
4212 | return result; |
4213 | } |
4214 | |
4215 | + /** |
4216 | + * Go through update folder and based on size estimate number of install checkpoint |
4217 | + * @param updateCommand update command file |
4218 | + * @return number of checkpoints |
4219 | + */ |
4220 | + private int estimateCheckpooint(String updateCommand) { |
4221 | + |
4222 | + long estimatedCheckCount = 0; |
4223 | + ReleaseType releaseType = ReleaseType.fromValue( // use delta as default for unknown updates |
4224 | + mSharedPreferences.getInt(PREF_KEY_DOWNLOAD_TYPE, ReleaseType.DELTA.getValue())); |
4225 | + File command = new File(updateCommand); |
4226 | + File updateFolder = command.getParentFile(); |
4227 | + if (updateFolder != null && updateFolder.isDirectory()) { |
4228 | + // looks for any file in this folder |
4229 | + File[] files = updateFolder.listFiles( |
4230 | + new FileFilter(){ |
4231 | + public boolean accept (File pathname) { |
4232 | + if (pathname.isFile() && pathname.getName().endsWith(".tar.xz")) { |
4233 | + return true; |
4234 | + } |
4235 | + return false; |
4236 | + } |
4237 | + }); |
4238 | + for (File f : files) { |
4239 | + if (f.getName().startsWith("ubuntu-")) { |
4240 | + estimatedCheckCount += (f.length() / PROGRESS_UBUNTU_ADJUSTMENT); |
4241 | + } else if (f.getName().startsWith("device-")) { |
4242 | + estimatedCheckCount += (f.length() / PROGRESS_DEVICE_ADJUSTMENT); |
4243 | + } else { |
4244 | + estimatedCheckCount += (f.length() / PROGRESS_CUSTOM_ADJUSTMENT); |
4245 | + } |
4246 | + } |
4247 | + } |
4248 | + if (releaseType == ReleaseType.DELTA) { |
4249 | + // set double checkpoints for removing files |
4250 | + estimatedCheckCount *=2; |
4251 | + } |
4252 | + return (int)estimatedCheckCount; |
4253 | + } |
4254 | + |
4255 | + /** |
4256 | + * Handle download error |
4257 | + */ |
4258 | private Intent handleDownloadError(Intent i, int res, String reason) { |
4259 | + mActionOutput += "\n" + reason; |
4260 | + if ( res == -2) { |
4261 | + // download canceled by user, dismiss progress notification |
4262 | + dismissProgressNotification(); |
4263 | + } else if (isUpdate()) { |
4264 | + showUbuntuNotification(R.string.notification_download_failed, LaunchActivity.class); |
4265 | + } else { |
4266 | + showUbuntuNotification(R.string.notification_download_failed, InstallActivity.class); |
4267 | + } |
4268 | i.putExtra(DOWNLOAD_RESULT_EXTRA_INT, res); |
4269 | i.putExtra(DOWNLOAD_RESULT_EXTRA_STR, reason); |
4270 | return i; |
4271 | } |
4272 | |
4273 | - private String doDownloadFile(JsonChannelParser.File file, File targetLocation) throws MalformedURLException, |
4274 | - FileNotFoundException, IOException, ECancelException { |
4275 | - URL url = new URL(BASE_URL + file.path); |
4276 | + private String doDownloadFile(String serverUrl, JsonChannelParser.File file, File targetLocation) |
4277 | + throws MalformedURLException, FileNotFoundException, IOException, ECancelException { |
4278 | + URL url = new URL(serverUrl + file.path); |
4279 | return doDownloadUrl(url, targetLocation, true); |
4280 | } |
4281 | |
4282 | - private String doDownloadFileSignature(JsonChannelParser.File file, File targetLocation) throws MalformedURLException, |
4283 | - FileNotFoundException, IOException, ECancelException { |
4284 | - URL url = new URL(BASE_URL + file.signature); |
4285 | - return doDownloadUrl(url, targetLocation); |
4286 | - } |
4287 | - |
4288 | - private String doDownloadUrl(URL url, File targertLocation) throws MalformedURLException, |
4289 | - FileNotFoundException, IOException, ECancelException { |
4290 | - return doDownloadUrl(url, targertLocation, false); |
4291 | - } |
4292 | - |
4293 | private String doDownloadUrl(URL url, File targertLocation, boolean resume) throws MalformedURLException, |
4294 | FileNotFoundException, IOException, ECancelException { |
4295 | Log.v(TAG, "Downloading:" + url.toString()); |
4296 | URLConnection conn = url.openConnection(); |
4297 | String fileName = URLUtil.guessFileName(url.toString(), null, null); |
4298 | - // TODO: update progress accordingly |
4299 | - broadcastProgress(mLastSignalledProgress, "Downloading: " + fileName); |
4300 | + broadcastProgress("Downloading: " + fileName); |
4301 | File file = new File(targertLocation, fileName); |
4302 | if ((! resume) && file.exists() && file.isFile()) { |
4303 | file.delete(); |
4304 | @@ -1011,7 +1348,7 @@ |
4305 | // resumePosition > 0 ==> append mode |
4306 | FileOutputStream output = new FileOutputStream(file, resumePosition > 0); |
4307 | |
4308 | - InputStream input = conn.getInputStream(); |
4309 | + final InputStream input = conn.getInputStream(); |
4310 | |
4311 | byte[] buffer = new byte[1024]; |
4312 | int len = 0; |
4313 | @@ -1021,9 +1358,18 @@ |
4314 | output.close(); |
4315 | conn = null; |
4316 | // input.close() need more time to close() as donwload large file. |
4317 | - input = null; |
4318 | + new Thread(new Runnable() { |
4319 | + @Override |
4320 | + public void run() { |
4321 | + try { |
4322 | + input.close(); |
4323 | + } catch (IOException e) { |
4324 | + e.printStackTrace(); |
4325 | + } |
4326 | + } |
4327 | + }).start(); |
4328 | long flen = file.length(); |
4329 | - if (flen > 0) { |
4330 | + if (flen > 0 && !resume) { |
4331 | try { |
4332 | file.delete(); |
4333 | flen = 0; |
4334 | @@ -1041,7 +1387,7 @@ |
4335 | if (mLastSignalledProgress < (mProgress * 100 / mTotalSize)) { |
4336 | // update and signal new progress |
4337 | mLastSignalledProgress = (int) (mProgress * 100 / mTotalSize); |
4338 | - broadcastProgress(mLastSignalledProgress, null); |
4339 | + broadcastProgress(null); |
4340 | } |
4341 | } |
4342 | output.flush(); |
4343 | @@ -1066,52 +1412,42 @@ |
4344 | } |
4345 | |
4346 | /** |
4347 | - * @return null if success or error |
4348 | + * Delete downloaded release |
4349 | */ |
4350 | - private String deleteRelease() { |
4351 | - // First delete old release if it exists |
4352 | - File rootFolder = new File(mRootOfWorkPath); |
4353 | - File release = new File(rootFolder, RELEASE_FOLDER); |
4354 | - if (release.exists()) { |
4355 | - deleteDirectory(release); |
4356 | - // cleanup update command |
4357 | - cleanUpdateCommand(); |
4358 | - // clean up version number. |
4359 | - VersionInfo.storeEmptyVersion(getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE).edit(), PREF_KEY_DOWNLOADED_VERSION); |
4360 | + private void doDeleteDownloadedRelease() { |
4361 | + // delete old release if it exists |
4362 | + if (mReleaseFolder.exists()) { |
4363 | + deleteDirectory(mReleaseFolder); |
4364 | } |
4365 | - return null; |
4366 | + // cleanup update command |
4367 | + cleanUpdateCommand(); |
4368 | + mSharedPreferences.edit() |
4369 | + .remove(PREF_KEY_DOWNLOAD_CHANNEL) |
4370 | + .remove(PREF_KEY_DOWNLOAD_SERVER) |
4371 | + .remove(PREF_KEY_DOWNLOAD_BOOTSTRAP) |
4372 | + .remove(PREF_KEY_DOWNLOAD_VERSION) |
4373 | + .putBoolean(PREF_KEY_DOWNLOAD_ACTIVE, false) |
4374 | + .putLong(PREF_KEY_DOWNLOAD_COMPLETED, 0) |
4375 | + .remove(PREF_KEY_DOWNLOAD_TYPE) |
4376 | + .commit(); |
4377 | } |
4378 | |
4379 | - private void broadcastInstallerState() { |
4380 | - Intent i = new Intent(SERVICE_STATE); |
4381 | - i.putExtra(SERVICE_STATE, mInstallerState.ordinal()); |
4382 | - sendBroadcast(i); |
4383 | - } |
4384 | - |
4385 | private void updateInstallerState(InstallerState newState) { |
4386 | - mInstallerState = newState; |
4387 | - Intent i = new Intent(SERVICE_STATE); |
4388 | - i.putExtra(SERVICE_STATE, mInstallerState.ordinal()); |
4389 | + mServiceState = newState; |
4390 | + Intent i = new Intent(SERVICE_STATE_CHANGED); |
4391 | sendBroadcast(i); |
4392 | } |
4393 | |
4394 | /** |
4395 | - * Check whether storage free space is enough. |
4396 | + * Check whether storage free space is enough for install or update |
4397 | * @param downloadSize: download size from json. 0 means file already downloaded. |
4398 | - * @return true if stoarge size is ok to go. |
4399 | + * @return true if storage size is ok to go. |
4400 | */ |
4401 | private boolean isStorageSpaceEnoughBFDownload(long downloadSize) { |
4402 | - long dataSizeRequired = INSTALL_SIZE_REQUIRED; |
4403 | - |
4404 | - if (workPathInCache) { |
4405 | - if (downloadSize > 0) { |
4406 | - long cacheFreeSpace = Utils.getFreeSpaceInBytes("/cache"); |
4407 | - if (cacheFreeSpace < EXTRA_SIZE_REQUIRED + downloadSize) { |
4408 | - return false; |
4409 | - } |
4410 | - } |
4411 | - } else { |
4412 | - dataSizeRequired += downloadSize; |
4413 | + long dataSizeRequired = downloadSize; |
4414 | + // if Ubuntu is already installed, we don't need that extra space, it will be freed |
4415 | + if (!mSharedPreferences.getBoolean(PREF_KEY_UBUNTU_INSTALLED, false)) { |
4416 | + dataSizeRequired += INSTALL_SIZE_REQUIRED; |
4417 | } |
4418 | |
4419 | long dataFreeSpace = Utils.getFreeSpaceInBytes("/data"); |
4420 | @@ -1121,114 +1457,127 @@ |
4421 | return true; |
4422 | } |
4423 | |
4424 | - private static VersionInfo getVersionWithPrefKey(Context c, String prefKey) { |
4425 | - SharedPreferences pref = c.getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE); |
4426 | - |
4427 | - if (VersionInfo.hasValidVersion(pref, prefKey)) { |
4428 | - return new VersionInfo(pref, prefKey); |
4429 | - } |
4430 | - return null; |
4431 | - } |
4432 | - |
4433 | - /** |
4434 | - * Internal helper function to get current DOWNLOAD_VERSION even download is partial |
4435 | - * @param context |
4436 | - * @return version info for download image. |
4437 | - */ |
4438 | - private static VersionInfo getDownloadVersion(Context context) { |
4439 | - return getVersionWithPrefKey(context, PREF_KEY_DOWNLOADED_VERSION); |
4440 | - } |
4441 | - |
4442 | - /** |
4443 | - * To get current DOWNLOAD_VERSION for completed download. |
4444 | - * @param context |
4445 | - * @return Version info for download-ed image. |
4446 | - */ |
4447 | - public static VersionInfo getDownloadedVersion(Context context) { |
4448 | - VersionInfo v = getVersionWithPrefKey(context, PREF_KEY_DOWNLOADED_VERSION); |
4449 | - if (v != null) { |
4450 | - if (v.mDownloadedSize == 0) return v; |
4451 | - } |
4452 | - return null; |
4453 | - } |
4454 | - |
4455 | - public static VersionInfo getInstalledVersion(Context c) { |
4456 | - return getVersionWithPrefKey(c, PREF_KEY_INSTALLED_VERSION); |
4457 | - } |
4458 | - |
4459 | - public static boolean isUbuntuInstalled(Context c) { |
4460 | - SharedPreferences pref = c.getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE); |
4461 | - if (VersionInfo.hasValidVersion(pref, PREF_KEY_INSTALLED_VERSION)) { |
4462 | - // go to launch screen |
4463 | - return true; |
4464 | - } |
4465 | - return false; |
4466 | - } |
4467 | - |
4468 | - /** |
4469 | - * check if update_command available for upgrade. |
4470 | - * |
4471 | - * @param c |
4472 | - * @return |
4473 | - */ |
4474 | - public static boolean isUpgradeable(Context c) { |
4475 | - String cmd = c.getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE).getString(PREF_KEY_UPDATE_COMMAND, ""); |
4476 | - return (cmd.startsWith("/cache/")); |
4477 | - } |
4478 | - |
4479 | - /** |
4480 | - * check if recovery command is exist on the system. |
4481 | + |
4482 | + /** |
4483 | + * Check if recovery command exists on the system. |
4484 | * system-image in Ubuntu Touch downloaded new version of image at /cache/recovery. |
4485 | * This function check if there is a ubuntu_command file in /cache/recovery. |
4486 | * |
4487 | * The ubuntu_command will be renamed or removed after installation. |
4488 | - * |
4489 | - * @return if there is upgradeable images stored in /cache. |
4490 | - */ |
4491 | - public boolean findInstallCommand () { |
4492 | - String[] candidates = { |
4493 | - "/cache/recovery/ubuntu_command", |
4494 | - "/cache/ubunturecovery/ubuntu_command", |
4495 | - }; |
4496 | - boolean ret = false; |
4497 | - for(String command: candidates) { |
4498 | - if(new File("/cache").canRead()) { |
4499 | - // if we have permission, we can read /cache. |
4500 | - File cmd = new File(command); |
4501 | - if(cmd.exists() && cmd.isFile()) { |
4502 | - Log.d(TAG, "Found upgrade command - " + cmd.getAbsoluteFile().toString()); |
4503 | - // find the upgradeable file, stored into pref. |
4504 | - setUpdateCommand(cmd.getAbsolutePath()); |
4505 | - ret = true; |
4506 | - } |
4507 | - } else { |
4508 | - // check the file with su |
4509 | - File workingFolder = new File(mRootOfWorkPath + "/" + TEMP_FOLDER); |
4510 | - if (!workingFolder.exists() && !workingFolder.mkdir()) { |
4511 | - Log.e(TAG, "can not create working folder"); |
4512 | - ret = false; |
4513 | - } |
4514 | - try { |
4515 | - int r = executeSUCommands(new String[] { |
4516 | - String.format("%s %s\n", UPGRADECHECKER, command), |
4517 | - }); |
4518 | - if(r == 1) { |
4519 | - Log.d(TAG, "Found upgradeable file - " + command); |
4520 | - setUpdateCommand(command); |
4521 | - ret = true; |
4522 | - } |
4523 | - } catch (EShellExecException e) { |
4524 | - ret = false; |
4525 | - } |
4526 | - } |
4527 | - } |
4528 | - if(ret) { |
4529 | - // FIXME we don't know what's the version in /cache. |
4530 | - SharedPreferences pref = getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE); |
4531 | - VersionInfo v = new VersionInfo(pref, PREF_KEY_INSTALLED_VERSION); |
4532 | - v.storeVersion(pref.edit(), PREF_KEY_DOWNLOADED_VERSION); |
4533 | - } |
4534 | - return ret; |
4535 | + */ |
4536 | + public void findPendingUpdates () { |
4537 | + |
4538 | + // check is there is update in linked upgrader folder |
4539 | + File linkedUpgrader = new File(getFilesDir(), LINKED_UPGRADER_COMMAND ); |
4540 | + File downloadedUpdate = new File(mReleaseFolder, UPDATE_COMMAND ); |
4541 | + boolean updateAvailable = false; |
4542 | + if (linkedUpgrader.exists()) { |
4543 | + updateAvailable = true; |
4544 | + setUpdateCommand(linkedUpgrader.getAbsolutePath()); |
4545 | + // parse file, if it has "format system", it will full install |
4546 | + if (Utils.parseAndUpdateInstallCommand(this,linkedUpgrader)) { |
4547 | + // remove channel and server so it's parsed from new install |
4548 | + mSharedPreferences.edit() |
4549 | + .remove(PREF_KEY_DOWNLOAD_CHANNEL) |
4550 | + .remove(PREF_KEY_DOWNLOAD_SERVER).commit(); |
4551 | + } |
4552 | + // if there is anything downloaded by this installer, we prefer updates from Ubuntu updater |
4553 | + if (mReleaseFolder.exists()) { |
4554 | + deleteDirectory(mReleaseFolder); |
4555 | + } |
4556 | + } else if (downloadedUpdate.exists()) { |
4557 | + updateAvailable = true; |
4558 | + setUpdateCommand(downloadedUpdate.getAbsolutePath()); |
4559 | + } |
4560 | + if (updateAvailable) { |
4561 | + mSharedPreferences.edit().putBoolean(PREF_KEY_PENDING_UPDATE,true); |
4562 | + sendBroadcast(new Intent(UBUNTU_UPDATE_PENDING)); |
4563 | + showUbuntuUpdateNotification(R.string.notification_update_available); |
4564 | + } |
4565 | + // check if there is also Android update |
4566 | + checkForPendingAndroidUpdate(); |
4567 | + File androidUpdate = new File(getFilesDir(), PENDING_ANDROID_UPDATE); |
4568 | + if (androidUpdate.exists()) { |
4569 | + // delete file, we don't need it anymore |
4570 | + androidUpdate.delete(); |
4571 | + sendBroadcast(new Intent(ANDROID_UPDATE_PENDING)); |
4572 | + // show notification only if it is desired by user |
4573 | + if (!mSharedPreferences.getBoolean(PREF_KEY_ANDROID_UPDATE_DISMISSED, false)) { |
4574 | + showAndroidUpdateNotification(); |
4575 | + } |
4576 | + } |
4577 | + } |
4578 | + |
4579 | + /** |
4580 | + * Check if there is pending android update zip package already downloaded |
4581 | + */ |
4582 | + private void checkForPendingAndroidUpdate() { |
4583 | + try { |
4584 | + executeSUCommands(new String[] { |
4585 | + String.format("if [[ ! -z $(busybox find /cache/ -maxdepth 1 -iname '*%s*%s*.zip') ]]; then touch %s/%s; chmod 777 %s/%s; fi\n", |
4586 | + Build.PRODUCT.toLowerCase(Locale.US), |
4587 | + Build.ID, |
4588 | + getFilesDir().toString(), |
4589 | + PENDING_ANDROID_UPDATE, |
4590 | + getFilesDir().toString(), |
4591 | + PENDING_ANDROID_UPDATE) |
4592 | + }); |
4593 | + } catch (EShellExecException e1) { |
4594 | + // ignore error |
4595 | + } |
4596 | + } |
4597 | + |
4598 | + /** |
4599 | + * Check if there is available update to be downloaded |
4600 | + */ |
4601 | + private void checkForAvailableUpdate() { |
4602 | + String channel = mSharedPreferences.getString(PREF_KEY_DOWNLOAD_CHANNEL, null); |
4603 | + String server = mSharedPreferences.getString(PREF_KEY_DOWNLOAD_SERVER, null); |
4604 | + if (channel == null || server == null) { |
4605 | + // no stored channel or server URL |
4606 | + return; |
4607 | + } |
4608 | + String jsonStr = Utils.httpDownload(String.format("%s/%s", server, channel)); |
4609 | + if (jsonStr != null) { |
4610 | + List<Image> releases = JsonChannelParser.getAvailableReleases(jsonStr, ReleaseType.DELTA); |
4611 | + if (releases.size() == 0 || releases.get(0).files.length == 0 ) { |
4612 | + // something is wrong, empty release |
4613 | + Log.e(TAG, "Empty releas"); |
4614 | + return; |
4615 | + } |
4616 | + // look for version with right base |
4617 | + String baseStr = mSharedPreferences.getString(PREF_KEY_VERSION_NUMBER, "0"); |
4618 | + int base = Integer.valueOf(baseStr); |
4619 | + for(Image r : releases) { |
4620 | + if (r.base == base) { |
4621 | + Log.d(TAG, "Found update to version:" + r.version); |
4622 | + mSharedPreferences.edit().putBoolean(PREF_KEY_PENDING_UPDATE, true).commit(); |
4623 | + Intent intent = new Intent(UBUNTU_UPDATE_AVAILABLE); |
4624 | + sendBroadcast(intent); |
4625 | + // show notification |
4626 | + showUbuntuUpdateNotification(R.string.notification_update_available); |
4627 | + return; |
4628 | + } |
4629 | + } |
4630 | + } |
4631 | + } |
4632 | + |
4633 | + /** |
4634 | + * Update used storage |
4635 | + * @return broadcast about data being updated |
4636 | + */ |
4637 | + private void doUpdateStorageUse() { |
4638 | + try { |
4639 | + executeSUCommands( |
4640 | + new String[]{ |
4641 | + String.format("busybox du -sm %s || true\n", UBUNTU_ROOTFS), |
4642 | + String.format("busybox du -sm %s || true\n", UBUNTU_SYSTEM_DATA), |
4643 | + String.format("busybox du -sm %s || true\n", UBUNTU_USER_DATA), |
4644 | + } ); |
4645 | + } catch (EShellExecException e) { |
4646 | + // ignore error |
4647 | + e.printStackTrace(); |
4648 | + } |
4649 | } |
4650 | |
4651 | /** |
4652 | @@ -1236,7 +1585,7 @@ |
4653 | * @file absolute file path of Ubuntu Command file. |
4654 | */ |
4655 | private String getUpdateCommand(){ |
4656 | - return getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE).getString(PREF_KEY_UPDATE_COMMAND, ""); |
4657 | + return mSharedPreferences.getString(PREF_KEY_UPDATE_COMMAND, ""); |
4658 | } |
4659 | |
4660 | /** |
4661 | @@ -1244,27 +1593,60 @@ |
4662 | * @file absolute file path of Ubuntu Command file. |
4663 | */ |
4664 | private void setUpdateCommand(String file){ |
4665 | - getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE). |
4666 | - edit(). |
4667 | - putString(PREF_KEY_UPDATE_COMMAND, file). |
4668 | - commit(); |
4669 | + mSharedPreferences.edit().putString(PREF_KEY_UPDATE_COMMAND, file).commit(); |
4670 | } |
4671 | |
4672 | /** |
4673 | * clean update command string stored in shared preferences. |
4674 | */ |
4675 | private void cleanUpdateCommand() { |
4676 | - this.setUpdateCommand(""); |
4677 | - } |
4678 | - |
4679 | - private void broadcastProgress(int val, String progress) { |
4680 | - Intent i = new Intent(PROGRESS); |
4681 | - i.putExtra(PROGRESS_EXTRA_INT, val); |
4682 | - if (progress!= null) { |
4683 | - i.putExtra(PROGRESS_EXTRA_TEXT, progress); |
4684 | + mSharedPreferences.edit() |
4685 | + .remove(PREF_KEY_UPDATE_COMMAND) |
4686 | + .commit(); |
4687 | + } |
4688 | + |
4689 | + /** |
4690 | + * Clean installed version info and all othe values |
4691 | + */ |
4692 | + private void setUbuntuUninstalled() { |
4693 | + mSharedPreferences.edit() |
4694 | + .remove(PREF_KEY_SIZE_ROOTFS) |
4695 | + .remove(PREF_KEY_VERSION_NUMBER) |
4696 | + .remove(PREF_KEY_VERSION_CHANNEL) |
4697 | + .remove(PREF_KEY_VERSION_CHANNEL_TARGET) |
4698 | + .remove(PREF_KEY_VERSION_DESCRIPTION) |
4699 | + .remove(PREF_KEY_VERSION_BASE) |
4700 | + .putBoolean(PREF_KEY_UBUNTU_INSTALLED, false) |
4701 | + .putBoolean(PREF_KEY_PENDING_UPDATE, false) |
4702 | + .commit(); |
4703 | + Utils.unregisterUpdateCheckAlarm(this); |
4704 | + dismissUbuntuNotification(); |
4705 | + dismissProgressNotification(); |
4706 | + dismissUbuntuUpdateNotification(); |
4707 | + } |
4708 | + |
4709 | + private void broadcastProgress(String progress) { |
4710 | + |
4711 | + Intent i = null; |
4712 | + if (progress == null) { |
4713 | + i = new Intent(PROGRESS); |
4714 | + // update notification |
4715 | + showProgressNotification(); |
4716 | + } else { |
4717 | + mActionOutput += "\n" + progress; |
4718 | + i = new Intent(PROGRESS_OUPUT); |
4719 | } |
4720 | sendBroadcast(i); |
4721 | } |
4722 | + |
4723 | + private boolean isNetworkAvailable() { |
4724 | + final ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); |
4725 | + final NetworkInfo activeNetwork = conMgr.getActiveNetworkInfo(); |
4726 | + if (activeNetwork != null && activeNetwork.isConnected()) { |
4727 | + return true; |
4728 | + } |
4729 | + return false; |
4730 | + } |
4731 | |
4732 | /** |
4733 | * Check if there is downloaded release ready to install. |
4734 | @@ -1272,25 +1654,157 @@ |
4735 | * @param context |
4736 | * @return true if there is downloaded release ready to install |
4737 | */ |
4738 | - public static boolean checkifReadyToInstall(Context context) { |
4739 | - SharedPreferences pref = context.getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE); |
4740 | - VersionInfo versionInfo = getDownloadVersion(context); |
4741 | - if (versionInfo == null) return false; |
4742 | - if (versionInfo.getDownloadedSize() != 0) return false; |
4743 | - |
4744 | - String command = pref.getString(PREF_KEY_UPDATE_COMMAND, ""); |
4745 | + public static boolean isReadyToInstall(SharedPreferences sp) { |
4746 | + String command = sp.getString(PREF_KEY_UPDATE_COMMAND, ""); |
4747 | Log.d(TAG, "checkifReadyToInstall"); |
4748 | - if (!command.equals("")) { |
4749 | - if (new File(command).exists() || command.startsWith("/cache")) { |
4750 | - Log.d(TAG, "checkifReadyToInstall - found command file " + command); |
4751 | - return true; |
4752 | + if (!command.equals("") && new File(command).exists() ) { |
4753 | + Log.d(TAG, "checkifReadyToInstall - found command file " + command); |
4754 | + return true; |
4755 | + } else { |
4756 | + sp.edit().remove(PREF_KEY_UPDATE_COMMAND).commit(); |
4757 | + return false; |
4758 | + } |
4759 | + } |
4760 | + |
4761 | + public static boolean isDownloadActive(SharedPreferences sp) { |
4762 | + return sp.getBoolean(UbuntuInstallService.PREF_KEY_DOWNLOAD_ACTIVE, false); |
4763 | + } |
4764 | + |
4765 | + public static void startInstallationIfPossible(Context c) { |
4766 | + // continue only if battery charge if over 30% |
4767 | + if ( MIN_INSTALL_BATTERY_CHARGE > getBatteryCharge(c) ) { |
4768 | + Utils.showToast(c, R.string.not_enough_charge_warning); |
4769 | + } else { |
4770 | + c.startService(new Intent(UbuntuInstallService.INSTALL_UBUNTU)); |
4771 | + } |
4772 | + } |
4773 | + |
4774 | + |
4775 | + public static int getBatteryCharge(Context c) { |
4776 | + IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); |
4777 | + Intent batteryStatus = c.registerReceiver(null, ifilter); |
4778 | + int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); |
4779 | + int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1); |
4780 | + return (level * 100 / scale); |
4781 | + } |
4782 | + |
4783 | + private void showUbuntuNotification(int textRsid, Class<?> act) { |
4784 | + Log.d(TAG, "showUbuntuNotification:" + getString(textRsid)); |
4785 | + dismissProgressNotification(); |
4786 | + mUbuntuNotification = showNotification(textRsid, |
4787 | + R.id.ubuntu_notification, act); |
4788 | + } |
4789 | + |
4790 | + private void showUbuntuUpdateNotification(int textRsid) { |
4791 | + mUbuntuUpdateNotification = showNotification(textRsid, |
4792 | + R.id.ubuntu_update_notification, |
4793 | + LaunchActivity.class); |
4794 | + } |
4795 | + |
4796 | + private void showAndroidUpdateNotification() { |
4797 | + mAndroidUpdateNotification = showNotification( |
4798 | + R.string.notification_android_update, |
4799 | + R.id.android_update_notification, |
4800 | + LaunchActivity.class); |
4801 | + } |
4802 | + |
4803 | + |
4804 | + private Notification showNotification(int textrRsid, int notificationId, Class<?> act) { |
4805 | + Intent updateActivity = new Intent(this, act); |
4806 | + updateActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); |
4807 | + PendingIntent pendingUpdate = PendingIntent.getActivity( |
4808 | + this, 0, updateActivity, PendingIntent.FLAG_UPDATE_CURRENT); |
4809 | + |
4810 | + Notification notification = new Notification.Builder(this) |
4811 | + .setAutoCancel(true) |
4812 | + .setSmallIcon(R.drawable.ic_stat_notify_ubuntu) |
4813 | + .setContentTitle(getString(R.string.notification_title)) |
4814 | + .setContentText(getString(textrRsid)) |
4815 | + .setTicker(getString(textrRsid)) |
4816 | + .setContentIntent(pendingUpdate) |
4817 | + .build(); |
4818 | + |
4819 | + mNotificationManager.notify(notificationId, notification); |
4820 | + return notification; |
4821 | + } |
4822 | + |
4823 | + private void showProgressNotification() { |
4824 | + // we are showing progress, no need for update notification |
4825 | + dismissUbuntuUpdateNotification(); |
4826 | + // choose text based on state downloading/installing and type FULL/DELTA |
4827 | + ReleaseType releaseType = ReleaseType.fromValue( // use delta as default for unknown updates |
4828 | + mSharedPreferences.getInt(PREF_KEY_DOWNLOAD_TYPE, ReleaseType.DELTA.getValue())); |
4829 | + int textRsid = 0; |
4830 | + if (mServiceState == InstallerState.DOWNLOADING) { |
4831 | + if (releaseType == ReleaseType.FULL) { |
4832 | + textRsid = R.string.notification_downloading_release; |
4833 | } else { |
4834 | - pref.edit().putString(PREF_KEY_UPDATE_COMMAND, "").commit(); |
4835 | - VersionInfo.storeEmptyVersion(pref.edit(), PREF_KEY_DOWNLOADED_VERSION); |
4836 | - return false; |
4837 | + textRsid = R.string.notification_downloading_update; |
4838 | } |
4839 | + } else if (mServiceState == InstallerState.INSTALLING) { |
4840 | + if (releaseType == ReleaseType.FULL) { |
4841 | + textRsid = R.string.notification_installing_release; |
4842 | + } else { |
4843 | + textRsid = R.string.notification_installing_update; |
4844 | + } |
4845 | + } else { |
4846 | + // don't show any notification |
4847 | + return; |
4848 | } |
4849 | - VersionInfo.storeEmptyVersion(pref.edit(), PREF_KEY_DOWNLOADED_VERSION); |
4850 | - return false; |
4851 | + Intent updateActivity = new Intent(this, InstallActivity.class); |
4852 | + updateActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); |
4853 | + PendingIntent pendingUpdate = PendingIntent.getActivity( |
4854 | + this, 0, updateActivity, PendingIntent.FLAG_UPDATE_CURRENT); |
4855 | + |
4856 | + mUbuntuProgressNotification = new Notification.Builder(this) |
4857 | + .setAutoCancel(true) |
4858 | + .setSmallIcon(R.drawable.ic_stat_notify_ubuntu) |
4859 | + .setContentTitle(getString(R.string.notification_title)) |
4860 | + .setContentText(getString(textRsid)) |
4861 | + .setTicker(getString(textRsid)) |
4862 | + .setContentIntent(pendingUpdate) |
4863 | + .setProgress(100, mLastSignalledProgress, false) |
4864 | + .build(); |
4865 | + mNotificationManager.notify(R.id.ubuntu_progress_notification, mUbuntuProgressNotification); |
4866 | } |
4867 | + |
4868 | + /** |
4869 | + * Dismiss progress notification |
4870 | + */ |
4871 | + public void dismissProgressNotification() { |
4872 | + if (mUbuntuProgressNotification != null) { |
4873 | + mNotificationManager.cancel(R.id.ubuntu_progress_notification); |
4874 | + mUbuntuProgressNotification = null; |
4875 | + } |
4876 | + } |
4877 | + |
4878 | + /** |
4879 | + * Dismiss Ubuntu notification |
4880 | + */ |
4881 | + public void dismissUbuntuNotification() { |
4882 | + if (mUbuntuNotification != null) { |
4883 | + mUbuntuNotification = null; |
4884 | + mNotificationManager.cancel(R.id.ubuntu_notification); |
4885 | + } |
4886 | + } |
4887 | + |
4888 | + /** |
4889 | + * Dismiss Ubuntu notification |
4890 | + */ |
4891 | + public void dismissUbuntuUpdateNotification() { |
4892 | + if (mUbuntuUpdateNotification != null) { |
4893 | + mUbuntuUpdateNotification = null; |
4894 | + mNotificationManager.cancel(R.id.ubuntu_update_notification); |
4895 | + } |
4896 | + } |
4897 | + |
4898 | + /** |
4899 | + * Dismiss Android notification |
4900 | + */ |
4901 | + public void dismissAndroidNotification() { |
4902 | + if (mAndroidUpdateNotification != null) { |
4903 | + mAndroidUpdateNotification = null; |
4904 | + mNotificationManager.cancel(R.id.android_update_notification); |
4905 | + } |
4906 | + } |
4907 | } |
4908 | |
4909 | === modified file 'src/com/canonical/ubuntu/installer/Utils.java' |
4910 | --- src/com/canonical/ubuntu/installer/Utils.java 2014-01-09 08:54:46 +0000 |
4911 | +++ src/com/canonical/ubuntu/installer/Utils.java 2014-06-09 11:59:50 +0000 |
4912 | @@ -1,14 +1,36 @@ |
4913 | +/* |
4914 | + * This file is part of Ubuntu dualboot installer for Android. |
4915 | + * Copyright 2013 Canonical Ltd. |
4916 | + * |
4917 | + * Ubuntu dualboot installer is free software: you can redistribute it and/or modify |
4918 | + * it under the terms of the GNU General Public License as published by |
4919 | + * the Free Software Foundation. |
4920 | + * |
4921 | + * Ubuntu dualboot installer is distributed in the hope that it will be useful, |
4922 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4923 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. |
4924 | + * See the GNU General Public License for more details. |
4925 | + * |
4926 | + * You should have received a copy of the GNU General Public License |
4927 | + * along with Ubuntu dualboot installer. If not, see <http://www.gnu.org/licenses/>. |
4928 | + */ |
4929 | + |
4930 | package com.canonical.ubuntu.installer; |
4931 | |
4932 | +import android.app.AlarmManager; |
4933 | import android.app.AlertDialog; |
4934 | +import android.app.PendingIntent; |
4935 | import android.content.Context; |
4936 | import android.content.DialogInterface; |
4937 | import android.content.Intent; |
4938 | +import android.content.SharedPreferences; |
4939 | import android.content.res.AssetManager; |
4940 | import android.net.wifi.WifiManager; |
4941 | import android.os.Build; |
4942 | import android.os.StatFs; |
4943 | import android.util.Log; |
4944 | +import android.view.Gravity; |
4945 | +import android.widget.TextView; |
4946 | import android.widget.Toast; |
4947 | |
4948 | import org.apache.http.HttpEntity; |
4949 | @@ -22,6 +44,7 @@ |
4950 | import java.io.File; |
4951 | import java.io.FileInputStream; |
4952 | import java.io.FileOutputStream; |
4953 | +import java.io.FileReader; |
4954 | import java.io.IOException; |
4955 | import java.io.InputStream; |
4956 | import java.io.InputStreamReader; |
4957 | @@ -30,6 +53,7 @@ |
4958 | import java.io.StringWriter; |
4959 | import java.io.Writer; |
4960 | import java.security.MessageDigest; |
4961 | +import java.util.ArrayList; |
4962 | import java.util.List; |
4963 | import java.util.Locale; |
4964 | |
4965 | @@ -191,18 +215,43 @@ |
4966 | } |
4967 | |
4968 | public static String getDeviceModel() { |
4969 | - return Build.DEVICE.toLowerCase(Locale.US); |
4970 | + String deviceModel = Build.DEVICE.toLowerCase(Locale.US); |
4971 | + if (deviceModel.equals("deb") || deviceModel.equals("tilapia")) { |
4972 | + deviceModel = "flo"; |
4973 | + } |
4974 | + if (isBringupMode()) { |
4975 | + deviceModel = "mako"; |
4976 | + } |
4977 | + return deviceModel; |
4978 | } |
4979 | |
4980 | public static boolean isDeviceSupported() { |
4981 | String path = getBootPartitionPath(); |
4982 | - if ("".equals(path)) return false; |
4983 | + if ("".equals(path)) { |
4984 | + return false; |
4985 | + } else { |
4986 | + return true; |
4987 | + } |
4988 | + } |
4989 | + |
4990 | + /** |
4991 | + * Check if device is in the list of know test devices |
4992 | + * of if we are in bringup mode |
4993 | + */ |
4994 | + public static boolean isBringupMode() { |
4995 | + if (!UbuntuInstallService.BRINGUP_MODE) { |
4996 | + String deviceModel = Build.DEVICE.toLowerCase(Locale.US); |
4997 | + if ("bq_aquaris5".equals(deviceModel)) { |
4998 | + return true; |
4999 | + } |
5000 | + return false; |
The diff has been truncated for viewing.
This has been dog food tested and released as version 1.0