Top 10 Tips For Developing Android Handsets

baroohspottyMobile - Wireless

Jul 19, 2012 (4 years and 11 months ago)

781 views

Top 10 Tips For Developing Android Handsets
Linux World 2008
Wayne Lee
PAGE 1
ƒ
Intro
Agenda
ƒ
䥮瑲I
ƒAndroid Overview
ƒTop 10 Tips
PAGE 2
Qualcomm and Android
ƒQualcomm is a founding member of the Open Handset Alliance (OHA)
ƒQualcomm sells integrated chips that power cell phones:
ƒ3G modem/GPS engine
ƒ
Applicationprocessor(thatrunsLinux/Android)
Application

processor

(that

runs

Linux/Android)
ƒPeripherals and multimedia acceleration cores
QlikiithGltittdtiiAdid
ƒ
Q
ua
l
comm
i
s wor
ki
ng w
ith

G
oog
l
e
t
o
i
n
t
egra
t
e an
d
op
ti
m
i
ze
A
n
d
ro
id
on
select Qualcomm multiprocessor chipsets (MSM7k, QSD8K)
PAGE 3
ƒ
Tipsandlessonslearnedforhandsetvendorswishingtodevelop
Scope of Talk
ƒ
呩灳

慮a

汥獳潮l

汥慲湥l

景f

桡湤獥h

癥湤潲v

睩獨楮w



摥癥汯d

桡湤獥瑳⁴桡琠獵灰潲琠䅮摲潩h
䙫l/didAdidHAL(HdAbttiL)
ƒ
F
ocus on
k
erne
l/d
r
i
vers an
d

A
n
d
ro
id

HAL

(H
ar
d
ware
Ab
s
t
rac
ti
on
L
ayer
)
ƒWill not cover Android in detail
ƒWill only give very brief overview of Android
ƒWill not cover upper layers of Android framework and app development
ƒ
䝯潧汥IO桡h汯瑳潦杯潤灲敳敮瑡瑩潮p

ƒ
䝯潧汥



桡h

汯瑳



杯潤

灲敳敮瑡瑩潮p


偁䝅‴
Android Architecture
PAGE 5
Source: http://sites.google.com/site/io/anatomy--physiology-of-an-android
ƒ
AndroidusesAndroid/LinuxnotGNU/Linux
Android: Kernel and HAL
ƒ
䅮摲潩A

畳敳

䅮摲潩搯䱩湵A

湯n

䝎唯䱩湵G
ƒKernel:
ƒLinux kernel 2.6.25 + patches
ƒ
Patches:ashmembinderpowermanagerlowmemorykillerkerneldebugger
Patches:

ashmem
,
binder
,
power

manager
,
low

memory

killer
,
kernel

debugger
,
logger, usb function driver
ƒSource: http://git.android.com
ƒHardware Abstraction Library
ƒAndroid interface to hardware
ƒAllows for kernel drivers or proprietary user-space drivers
ƒSupports drivers without standard APIs (e.g. vibrator)
PAGE 6
ƒ
SurfaceFlinger
Android: Display & Multimedia
ƒ
卵牦慣敆汩湧敲
ƒServer to compose 2D/3D surfaces from multiple apps onto the framebuffer
ƒCan use 2D/3D HW accelerators to blit, rotate, scale, blend, etc.
ƒOpenGL ES library
ƒEither software or hardware accelerated im
p
lementations can be used
p
ƒMedia Framework based on PacketVideo OpenCORE
Stdiidiid
ƒ
S
uppor
t
s au
di
o, v
id
eo,
i
mag
i
ng co
d
ecs
ƒPluggable architecture for hardware/software codecs

Uses OpenMAX IL interface
ƒAudioFlinger
ƒ
Servertomixaudiochannelsfrommultipleappstoaudiodevices
PAGE 7
Server

to

mix

audio

channels

from

multiple

apps

to

audio

devices
ƒ
http://codegooglecom/android
Good Android Links
ƒ
桴瑰㨯hc潤o
.
杯潧汥
.
捯洯慮摲潩c
ƒhttp://sites.google.com/site/io/anatomy--physiology-of-an-android
ƒhttp://sites.google.com/site/io/inside-the-android-application-framework
ƒhttp://sites.google.com/site/io/dalvik-vm-internals
ƒhttp://www.android-internals.org
PAGE 8
1
UnderstandOpenSourcelicenses
Top 10 Tips
1
.
Understand

Open

Source

licenses
2.Booting Linux and Android
3.I want my ADB!
4.Drivers: kernel or user-space?
5.The RIL Shim Layer
6.Accelerate Multimedia in HW
7.Add a good GPS solution
8.Maximize performance, minimize power
9.Misc
10
AIttdAdidlti
10
.
A
n
I
n
t
egra
t
e
d

A
n
d
ro
id
so
l
u
ti
on
PAGE 9
1
UnderstandOpenSourcelicenses
Top 10 Tips
1
.
Understand

Open

Source

licenses
2.Booting Linux and Android
3.I want my ADB!
4.Drivers: kernel or user-space?
5.The RIL Shim Layer
6.Accelerate Multimedia in HW
7.Add a good GPS solution
8.Maximize performance, minimize power
9.Misc
10
AIttdAdidlti
10
.
A
n
I
n
t
egra
t
e
d

A
n
d
ro
id
so
l
u
ti
on
PAGE 10
Usual legal disclaimers from an engineer
ƒIANAL (I am not a lawyer)
ƒTINLA (This is not legal advice)
PAGE 11
ƒ
LinuxKernelislicensedGPL
Spend Time to Understand Open Source Software (OSS) licenses
ƒ
䱩湵L

䭥牮敬



汩捥湳敤

䝐G
ƒMost of Android will be licensed as Apache v2
ƒGPL and Apache:
ƒ“ASL [Apache Software License] … is a permissive license that is conducive to
commercial development and proprietar
y
redistribution. Code that is distributed
y
under the ASL and other permissive licenses can be integrated into closed-
source proprietary products and redistributed under a broad variety of other
terms. Unlike permissive open-source licenses, "copyleft" licenses (such as the
GPL)generallyimposerestrictionsonredistributionofcodeinordertoensure
GPL)

generally

impose

restrictions

on

redistribution

of

code

in

order

to

ensure

that modifications and derivatives are kept open and distributed under similar
terms.”
ƒSource: http://arstechnica.com/news.ars/post/20071106-why-google-chose-the-
apache-software-license-ove
r
-gplv2.html
ƒOSS license can affect software desi
g
n
PAGE 12
g
1
UnderstandOpenSourcelicenses
Top 10 Tips
1
.
Understand

Open

Source

licenses
2.Booting Linux and Android
3.I want my ADB!
4.Drivers: kernel or user-space?
5.The RIL Shim Layer
6.Accelerate Multimedia in HW
7.Add a good GPS solution
8.Maximize performance, minimize power
9.Misc
10
AIttdAdidlti
10
.
A
n
I
n
t
egra
t
e
d

A
n
d
ro
id
so
l
u
ti
on
PAGE 13
Booting Linux/Android
1.Boot Linux from RAM
ƒStart with Linux kernel with Android patches (android-2.6.25 on
htt//itdid
)
htt
p:
//
g
it
.an
d
ro
id
.com
)
ƒBasic arch/board files (io, irq, timers)
ƒUse JTAG to init RAM, create ATAGS, cmdline args, r0/r1/r2
ƒLoad kernel to RAM and run.
2.A
dd

a

s
im
p
l
e
r
oot
r
a
m
d
i
s
k fil
esyste
m
a
n
d

co
n
so
l
e
ddaspeootadsesysteadcosoe
ƒAdd UART or DCC (JTAG on ARM) drivers for console
ƒUse busybox for UNIX tools
PAGE 14
Booting Linux/Android
3.Get critical drivers working (needed for basic Android booting)
ƒUSB (needed for ADB and flashing)
ƒMTD (NAND) / filesystem
4.
BootfromFlash
4.
Boot

from

Flash
ƒNeed mechanism to flash (bootloader/USB/Ethernet or JTAG)
ƒUpdate bootloader to load kernel/ramdisk from flash
ƒ
呩瀺偵Pt桥步牮敬⽲慭摩獫楮a湯牭慬灡牴楴楯p湯n楮af楬敳祳瑥i⡳業灬楦楥(
ƒ
呩瀺

偵P

瑨t

步牮敬⽲慭摩獫



a

湯牭慬

灡牴楴楯p

湯n



a

晩汥獹獴敭

⡳業灬楦楥(

扯潴汯慤敲b
ƒTip: Boot from network (TFTP) (saves flash time)
PAGE 15
Booting Linux/Android
5.Add basic UI drivers
ƒFramebuffer
ƒKeypad/Trackball
6.Build and boot Android
ƒBuild Android from source
ƒFlash Android system image
7.Add remaining drivers
ƒModem, Data, GPS
ƒAudio, Camera, Video, Graphics
ƒWiFi, SD, Bluetooth
ƒTouch
p
ad
,
Sensors
,
Batter
y
PAGE 16
p,,y
1
UnderstandOpenSourcelicenses
Top 10 Tips
1
.
Understand

Open

Source

licenses
2.Booting Linux and Android
3.I want my ADB!
4.Drivers: kernel or user-space?
5.The RIL Shim Layer
ANDROID DEBUG BRIDGE
6.Accelerate Multimedia in HW
7.Add a good GPS solution
8.Maximize performance, minimize power
9.Misc
10
AIttdAdidlti
10
.
A
n
I
n
t
egra
t
e
d

A
n
d
ro
id
so
l
u
ti
on
PAGE 17
ƒ
AndroidDebugBridge(ADB)isessentialforAndroid
Get ADB (and USB) working early
ƒ
䅮摲潩A

䑥扵D

䉲楤来

⡁䑂(



敳獥湴楡e

景f

䅮摲潩A

摥癥汯灭敮琯摥扵杧楮d
ƒRequires USB
ƒADB is used for:
ƒMoving files to and from the device (adb push/pull/sync)
ƒ
䱯杧敲⡡摢汯杣慴l
ƒ
䱯杧敲

⡡摢

汯杣慴l
–
䝥琠汯杳渠愠灥爠獵扳祳瑥洯癥G扯獥⁢慳楳⸠⁖敲礬⁶敲礠畳敦畬
ƒRunning shell commands (mv, dmesg, reboot, ps, top, etc)

Ti
p
:
%

adb

s
h
e
ll <
c
m
d
>
p%adbsecd
ƒStop and restart services (adb shell start/stop)
ƒTCP port forwarding (adb forward)

Needed for remote
g
db debu
gg
in
g
gggg
ƒPlus more!
ƒhtt
p
://code.
g
oo
g
le.com/android/reference/adb.html
PAGE 18
pgg
ƒ
Getbootloaderworkingwiththefastbootprotocol
Fastboot and other tools
ƒ
䝥G

扯潴汯慤敲

睯牫楮w

睩瑨

瑨t

晡獴扯潴

灲潴潣潬
ƒRequires USB + fastboot protocol
ƒAllows for flashing of bootloader, boot (kernel/ramdisk), and system images
ƒCould also be used for flashing other firmware (e.g. modem)
ƒMore tools
ƒStack –dumps call stack of all processes from logcat crash output
ƒRemote GDB to debug System Servers
ƒ
䕣汩灳E睩瑨A湤牯楤p汵杩lto摥扵d䅮摲潩A慰灳
ƒ
䕣汩灳E

睩瑨

䅮摲潩A

灬畧楮



摥扵d

䅮摲潩A

慰灳
偁䝅‱P
1
UnderstandOpenSourcelicenses
Top 10 Tips
1
.
Understand

Open

Source

licenses
2.Booting Linux and Android
3.I want my ADB!
4.Drivers: kernel or user-space?
5.The RIL Shim Layer
6.Accelerate Multimedia in HW
7.Add a good GPS solution
8.Maximize performance, minimize power
9.Misc
10
AIttdAdidlti
10
.
A
n
I
n
t
egra
t
e
d

A
n
d
ro
id
so
l
u
ti
on
PAGE 20
ƒ
Kernel
Drivers: Kernel or User-space
ƒ
䭥牮敬
ƒMust be GPL
ƒKernel manages multiple clients, security based on file permissions
ƒExcellent Linux driver model
ƒLeverages existing kernel drivers
ƒE.g: BlueZ, SDIO
ƒUser-space library (part of the HAL)
ƒ
Canbeproprietary(someexceptions)
Can

be

proprietary

(some

exceptions)
ƒUse UIO or lightweight driver to map hardware memory and proxy interrupts
ƒMay perform better (no need to trap into kernel, sometimes no copying)
ƒ
䵯牥摩晦楣畬d瑯獵灰潲sm畬瑩灬uc汩敮瑳
ƒ
䵯牥

摩晦楣畬d



獵灰潲s

浵汴楰汥

捬楥湴c
ƒSecurity is important: kernel must ensure user-space does not program HW to
scribble over system memory
ƒ
Eg㍄杲慰桩捳摲楶敲
偁䝅′P
ƒ
E
.
g



杲慰桩捳

摲楶敲
ƒ
Portinglegacydriverstokernelmaynotbebestoption
Porting Drivers
ƒ
偯牴楮P

汥条捹

摲楶敲d



步牮敬

浡m

湯n



扥獴

潰瑩潮
ƒFundamental different driver architectures:

Legacy RTOS drivers are task/event loop driven.
Lidiblki

Li
nux
d
r
i
vers are
bl
oc
ki
ng
ƒPure Linux driver are often easier to read/debug and better performing
ƒMay be tough (impossible?) to push upstream to kernel.org
ƒPorting layers of layers of software may not be best option
ƒ
Resultsinslowerperformance,itaddsup.
Results

in

slower

performance,

it

adds

up.
ƒConsider the size of cache
ƒSometimes better to rewrite
PAGE 22
1
UnderstandOpenSourcelicenses
Top 10 Tips
1
.
Understand

Open

Source

licenses
2.Booting Linux and Android
3.I want my ADB!
4.Drivers: kernel or user-space?
5.The RIL Shim Layer
6.Accelerate Multimedia in HW
7.Add a good GPS solution
8.Maximize performance, minimize power
9.Misc
10
AIttdAdidlti
10
.
A
n
I
n
t
egra
t
e
d

A
n
d
ro
id
so
l
u
ti
on
PAGE 23
ƒ
RadioInterfaceLayer(RIL)
The RIL Shim Layer
ƒ
剡摩R

䥮瑥牦慣I

䱡祥L

⡒䥌(
ƒHAL interface between the Android TelephonyManager and the baseband
modem
ƒVoice
,
Data
,
SMS
,
SIM
,
SIMToolkit
,,,,
ƒAndroid includes a reference AT command based RIL
ƒ
RILAPI
RIL

API
ƒCurrently 75 requests (e.g. Dial) and 17 unsolicited responses (e.g. signal
strength)
ƒAndroid RIL inspired by GSM TS 27.007
ƒCan implement as AT command based or proprietary protocol (e.g. RPCs via
shared memory)
ƒEnhancing the RIL
ƒCarriers may require specific features (e.g. JCDMA, O2 Homezone)
ƒQualcomm working on adding CDMA and Multi-mode support
PAGE 24
ƒ
Certification
The RIL Shim Layer
ƒ
䍥牴楦楣慴楯C
ƒGCF
ƒCDG
ƒTips
ƒSIM and SIM Toolkit is com
p
lex
,

g
et an ex
p
ert
p,gp
ƒRIL needs to provide neighboring cell id (non-standard). Used by Google
Maps.
ƒData: su
gg
est
p
acket interface, no DHCP, no PPP.
ggp
ƒDepending on modem interface, RIL may get complicated with lots of
logic/state.
ƒAndroid data is alwa
y
s-on, modem should su
pp
ort dormanc
y
y
ppy
PAGE 25
The RIL Shim Layer
PAGE 26
1
UnderstandOpenSourcelicenses
Top 10 Tips
1
.
Understand

Open

Source

licenses
2.Booting Linux and Android
3.I want my ADB!
4.Drivers: kernel or user-space?
5.The RIL Shim Layer
6.Accelerate Multimedia in HW
7.Add a good GPS solution
8.Maximize performance, minimize power
9.Misc
10
AIttdAdidlti
10
.
A
n
I
n
t
egra
t
e
d

A
n
d
ro
id
so
l
u
ti
on
PAGE 27
ƒ
SoftwarecodecsrequireslotsofCPU
Accelerating Multimedia in Hardware
Software

codecs

requires

lots

of

CPU
ƒMay not meet performance metrics (fps, bitrate, resolution, triangles/sec)
ƒMay consume too much power (CPU running, high clock rate)
ƒPrevents other apps from running well.
ƒH.264 decode example
ƒSoftware codecs maxed CPU out at QVGA (320x240)
ƒHardware codecs able to achieve HVGA (480x360) at 500kbps, 30fps, using very little
ARM11 CPU @ 528MHz for high level video processing
ƒ
Androideasilysupportsacceleration:
Android

easily

supports

acceleration:
ƒAudio via the audio HAL

Can sit under OpenMAX IL or ALSA or OSS or native
ƒVideo and imaging via OpenMAX IL interface
ƒ3D via OpenGL ES lib
ƒSurface composition via HAL (2D or 3D)

Can accelerate blt, rotating, scaling, blending, etc
PAGE 28
ƒ
Tips
Accelerating Multimedia in Hardware
ƒ
呩灳
ƒReduce memcpy
ƒExcessive layers and threads increases context switches, blows cache, and
reducesperformance
reduces

performance

Consider rewriting instead of pulling in large frameworks as is
ƒQueue large buffers, then sleep
PAGE 29
Accelerating Multimedia in Hardware
PAGE 30
Source: http://sites.google.com/site/io/anatomy--physiology-of-an-android
1
UnderstandOpenSourcelicenses
Top 10 Tips
1
.
Understand

Open

Source

licenses
2.Booting Linux and Android
3.I want my ADB!
4.Drivers: kernel or user-space?
5.The RIL Shim Layer
6.Accelerate Multimedia in HW
7.Add a good GPS solution
8.Maximize performance, minimize power
9.Misc
10
AIttdAdidlti
10
.
A
n
I
n
t
egra
t
e
d

A
n
d
ro
id
so
l
u
ti
on
PAGE 31
ƒ
Today

smobiledevices/servicesdemandlocationawaredevices
Add a good GPS solution
ƒ
呯摡Ts

浯扩汥

摥癩捥猯獥牶楣敳

摥浡湤

汯捡瑩潮

慷慲a

摥癩捥d
ƒLocation technologies
ƒGPS (unassisted)
ƒAGPS (network assisted)

Get sat info from network, compute on device/server
ƒOther tricks

WiFi location

Cell tower triangulation

XTRA
ƒLocation metrics:
ƒTime to first fix (cold, warm)
ƒAccuracy (under different environments)
PAGE 32
Add a good GPS solution
ƒLocation Manager runs in System Server process
ƒLinks with GPS HAL lib

Can use standard NMEA, o
r

Interface specific to hardware (e.g. RPC)
ƒAndroid may not support all GPS features
ƒWill be open source for community to augment
PAGE 33
Add a good GPS solution
PAGE 34
Source: http://sites.google.com/site/io/anatomy--physiology-of-an-android
1
UnderstandOpenSourcelicenses
Top 10 Tips
1
.
Understand

Open

Source

licenses
2.Booting Linux and Android
3.I want my ADB!
4.Drivers: kernel or user-space?
5.The RIL Shim Layer
6.Accelerate Multimedia in HW
7.Add a good GPS solution
8.Maximize performance, minimize power
9.Misc
10
AIttdAdidlti
10
.
A
n
I
n
t
egra
t
e
d

A
n
d
ro
id
so
l
u
ti
on
PAGE 35
ƒ
Performanceandpowerareoftenatodds
Maximize Performance, Minimize Power
Performance

and

power

are

often

at

odds
ƒPlan for this process to take some time
ƒSuspend/Idle
ƒ
A
ndroid aggressively enter suspend.

Carefully use Android suspend locks (wake locks)

Can’t take too long to enter/exit suspend
ƒShut down as much as possible in idle
Midditilittlt(?)

M
ay
i
ncur a
dditi
ona
l

i
n
t
errup
t

l
a
t
ency
(
pm_qos
?)
ƒSynchronize wakeup events (BT, WiFi, 3G sleep, System)
ƒClocks
ƒDesign frequency plan to reduce active oscillators/PLLs per “user-case” (standby, talk, audio, video)
ƒScale CPU/bus speed depending on load

Use cpufreq and optimize governor algorithm
ƒDevices
ƒPlace device and GPIO pads in low power mode when in suspend/idle and when disabled
ƒDisable clocks and voltage regulators when in low power mode
ƒ
䑩獡扬DL䍄⽢慣歬楧桴睨敮湯n楮畳u(eg湯畳敲慣瑩癩瑹慵摩ap污祢慣欩
偁䝅″P
ƒ
䑩獡扬D

䱃䐯扡捫汩杨L

睨敮

湯n



畳u


.
g



畳敲

慣瑩癩瑹

慵摩a

灬慹扡捫p
ƒ
Tips:
Maximize Performance, Minimize Power
ƒ
呩灳T
ƒUse tickless kernel and deferred timers
ƒUse lower power dedicated hardware (e.g. multimedia) instead of power
hungryCPU
hungry

CPU
ƒShift to low power memory
PAGE 37
1
UnderstandOpenSourcelicenses
Top 10 Tips
1
.
Understand

Open

Source

licenses
2.Booting Linux and Android
3.I want my ADB!
4.Drivers: kernel or user-space?
5.The RIL Shim Layer
6.Accelerate Multimedia in HW
7.Add a good GPS solution
8.Maximize performance, minimize power
9.Misc
10
AIttdAdidlti
10
.
A
n
I
n
t
egra
t
e
d

A
n
d
ro
id
so
l
u
ti
on
PAGE 38
ƒ
Factoryprovisioning
Misc things to not forget about
ƒ
䙡捴潲F

灲潶楳楯湩湧
ƒSoftware upgrade
OTA
ƒ
OTA
ƒOperator specific customizations
ƒVFLive, Orange Homescreen, etc.
ƒScreen size customizations
ƒAndroid 1.0 currently optimized for HVGA
ƒMay require adjustments to apps, fonts, icons for different screen size
ƒOEM customizations
ƒDifferentiate your Android solution from competitors
ƒ
周敭敳捵獴潭慰灬楣慴楯湳整e
偁䝅″P
ƒ
周敭敳

捵獴潭

慰灬楣慴楯湳

整e
.
ƒ
Supportrestartingofcrashedmodules/devices
Misc things to not forget about
ƒ
卵灰潲S

牥獴慲瑩湧



捲慳桥c

浯摵汥猯摥癩捥m
ƒRIL, modem

System must allow for modem restart
S/HAL(GPSAdiVid3DIiGPSBltthWiFi)
ƒ
S
ervers
/HAL

(GPS
,
A
u
di
o,
Vid
eo,
3D
,
I
mag
i
ng,
GPS
,
Bl
ue
t
oo
th
,
WiFi)

System must allow for Server restarts
PAGE 40
1
UnderstandOpenSourcelicenses
Top 10 Tips
1
.
Understand

Open

Source

licenses
2.Booting Linux and Android
3.I want my ADB!
4.Drivers: kernel or user-space?
5.The RIL Shim Layer
6.Accelerate Multimedia in HW
7.Add a good GPS solution
8.Maximize performance, minimize power
9.Misc
10
AIttdAdidlti
10
.
A
n
I
n
t
egra
t
e
d

A
n
d
ro
id
so
l
u
ti
on
PAGE 41
ƒ
PortingAndroidtotargetplatformandintegratingHWaccelerationtakes
A vertically integrated and optimized Android solution?
ƒ
偯牴楮P

䅮摲潩A



瑡牧整

灬慴景牭

慮a

楮瑥杲慴楮i



慣捥汥牡瑩潮

瑡步t

瑩浥t
ƒKernel/Driver (BSP)
RILithd(ithtifiti)
ƒ
RIL
w
ith
mo
d
em
(
w
ith
cer
tifi
ca
ti
on
)
ƒIntegrated Multimedia with HW accelerators (audio, video, imaging, camera,
2D, 3D)
GPSBltthWiFi
ƒ
GPS
,
Bl
ue
t
oo
th
,
WiFi
ƒMaximize performance, minimize power
ƒConsider starting with pre-integrated, optimized components from OHA
silicon vendor and software commercialization members.
ƒAllows OEMs to focus on differentiating Android features (apps, UIs,
novel designs)
PAGE 42
1
UnderstandOpenSourcelicenses
Top 10 Tips
1
.
Understand

Open

Source

licenses
2.Booting Linux and Android
3.I want my ADB!
4.Drivers: kernel or user-space?
5.The RIL Shim Layer
6.Accelerate Multimedia in HW
7.Add a good GPS solution
8.Maximize performance, minimize power
9.Misc
10
AIttdAdidlti
10
.
A
n
I
n
t
egra
t
e
d

A
n
d
ro
id
so
l
u
ti
on
PAGE 43
Thankyou!
Thank

you!
PAGE 44