diff --git a/docs/lectures/mdp/01_mobile_architeture.md b/docs/lectures/mdp/01_mobile_architeture.md new file mode 100644 index 0000000..ce3883a --- /dev/null +++ b/docs/lectures/mdp/01_mobile_architeture.md @@ -0,0 +1,122 @@ +# Mobile Architecture + +#### Typical Motherboard of a PC + +![img](img/a.png) + +##### North-bridge + +* Links the CPU to high-speed devices like RAM, GPU, etc. + +##### South-bridge + +Connects to low-speed devices like IO devices, PCI devices, ROM/BIOS, etc. + +![img](img/b.png) + +#### Connections + +* The CPU has a bus that connects it to the other chips (address, data and control buses) + * Buses create a lot of heat; this bottlenecks mobile devices. +* Nowadays more advanced buses are used: **HyperBus**. + +![img](img/c.png) + +Intel Pentium Chip (1993) - put all different components on one chip to save power. This is the same logic mobile devices use. + +#### System on a Chip (SoC) + +* The whole system is literally on a single chip + +> * Aims to reduce communications overhead +> * Aims to reduce heat + +The chip is divided into multiple regions, each of which deals with a different task, and is built block by block from descriptions of separate parts. + +* CPU core +* GPU core +* RAM core +* Qualcomm Snapdragon +* Apple A4-A13 +* Texas Instruments OMAP + +**All use the same CPU block**: ARM Cortex A\* + +![img](img/d.png) + +##### Package on Package + +* RAM is normally not included in SoC + * Uses a lot of space +* It is a separate package stacked on top of the SoC + * Stacked to save space + +![img](img/e.png) + +#### ARM CPU vs Intel x86 + +* Almost all smartphones use ARM CPUs + +**Why?** + +* Fast and efficient + * Higher code density + * Better utilisation of space +* Less power consumption + * Intel: ~45W vs ARM ~3W +* ARM is sold as a design, not a physical device + * Great for SoC usage. Chip manufacturers can add an ARM CPU to a bespoke SoC rather than buying a set chip from Intel. +* x86 chips can take many cycles, whereas ARM aims for one instruction per cycle + +##### ARM CPU + +ARM uses a RISC + +RISC: add two numbers: + +```assembly +ADD R1, R2, R3 +``` + +CISC: add two numbers: + +```assembly +POP num1 +POP num2 +ADD num1, num2, result +PUSH result +``` + +* ARM has a fixed instruction width of 32 bits + * Makes decoding easier & more efficient + +###### ARM CPU Registers + +* 13 general purpose registers (r0-r12) + * r13 stack pointer + * r14 link register + * r15 program counter + +![img](img/f.png) + +A register performing a data processing instruction + +##### ARM and Thumb + +* Every ARM instruction is 32 bits long + * Can take up a lot of memory - poor code density + * Memory accesses take time + * Not all memory needs 32 bits +* Thumb + * 16-bit version of the ARM instruction set + * Variable length instruction set + * Can run 2 thumbs in parallel + * One 32-bit read gives two 16-bit instructions + +##### ARM big.LITTLE + +ARM's processor contains low and high-performance cores + +* Two cores are architecturally consistent +* System can switch between the two as appropriate for the task + * e.g. idling - low-performance core \ No newline at end of file diff --git a/docs/lectures/mdp/02_android_os.md b/docs/lectures/mdp/02_android_os.md new file mode 100644 index 0000000..8c35aec --- /dev/null +++ b/docs/lectures/mdp/02_android_os.md @@ -0,0 +1,101 @@ +# Introduction to Android + +![img](img/g.png) + +**Linux Kernel**: threading, low-level memory management, driver + +**Hardware Abstraction Layer:** Libraries for hardware modules, because different devices have different hardware + +**Android Runtime:** A virtual machine + +**Native C/C++ Libraries:** Libraries for rendering & fundamental core functionalities + +**Java API Framework:** Programming interface + +**System Apps:** Normal apps that can be customised. + +#### Android-Specific Mods + +Android is based on Linux with some key differences: + +* Wake locks - keep the phone awake +* Binder - inter-process communication; this is so no app can communicate with others, otherwise banking apps could be compromised +* `ashmem` - shared memory +* oom - kills processes when memory is low +* alarm manager - wakes up the phone when necessary (raise to wake) + +#### Android Apps + +* Applications are sandboxed + * A security mechanism for separately running applications and data +* Android application sandbox + * Linux is a multi-user system - this isn't needed + * Makes use of Linux permissions and security + * No root access + +#### System Boot-up Process + +1. **Boot ROM/Bootloader**: Load bootloader into RAM, detect external RAM, set up network, memory, etc. +2. **Kernel**: Set up cache, protected memory, scheduling and load drivers +3. **Init**: Mount directories like `/sys`, `/dev` and run `rc` scripts. +4. **Zygote & VM**: Enables code sharing across the Android VM for quick startup of separate VMs for different apps +5. **System service**: Power manager, activity manager, telephony registry, package manager. + +##### Zygote + +* Initialise a process that has all core libraries linked in. +* Load all `*.java` and `*.android` classes at boot. +* Initially create a single Android VM process +* When the user runs an application + * Creates a copy of itself in a separate address space + * Does not copy memory; instead, refers to original memory until modified + +![img](img/h.png) + +#### Android Compilation + +* Applications are written in Java and run on Google's own VM - Dalvik/Android Runtime + + ![img](img/i.png) + +* `.apk` is analogous to `.exe` + +##### Dalvik + +* Dalvik architecture is register-based rather than stack-based. + * This makes it optimised to use less space +* Executes its own Dalvik bytecode rather than Java bytecode + +![img](img/j.png) + +##### Android Programming Model + +* Traditional OS applications + * Single entry point - `main()` + * OS loads the program into a process and executes +* Java Applications + * A Java VM is instantiated + * Loads all classes used by the application + * Executes `main()` +* Component-based model + * Multiple entry points - think sharing a photo through WhatsApp; WhatsApp loads in a different way. + * Not all entry points are for the user + +###### 4 Main Components + +Communicating via specific interfaces + +* Inter-process - between +* Intra-process - within +* Bound at runtime + * Each with a specific life cycle + * Dynamically loaded and unloaded as necessary + +1. **Activities** + * UI components +2. **Services** + * Mechanism for doing something long-running in the background (front-end / back-end) +3. **Broadcast Receivers** + * Respond to broadcast messages from the OS / other apps +4. **Content Providers** + * Make data available for use by other apps diff --git a/docs/lectures/mdp/03_activities.md b/docs/lectures/mdp/03_activities.md new file mode 100644 index 0000000..9436e03 --- /dev/null +++ b/docs/lectures/mdp/03_activities.md @@ -0,0 +1,82 @@ +# Activities + +Subclasses of **android.app.Activity** + +- Present a visual UI +- Each activity has its own 'window' + - Only one 'window' on screen at once + - **Granular management** of the resources of an application + - UI layout - a 'view' + - Specified in a separate XML file + - Constructed programmatically + - Apps usually have several activities + +#### Android UI + +An activity has a window associated with it - usually full screen. + +![img](img/k.png) + +#### View Hierarchy + +There are 3 types of views: + +1. Those that display something (`Views`) +2. Those that do something (`Widgets`) +3. Those that lay out sub-views (`ViewGroups`) + +##### View Principles + +Mobile devices are rarely the same, i.e. they have different screen sizes & resolutions + +* Layout should **adapt** to the screen it is inflated in + * No hard-coding, layouts are defined in hierarchies and relationships. +* Different layouts for orientation + +###### ViewGroups + +* Frame Layout + * Simplest - contains a single object +* Linear Layout + * Aligns all children in a single direction +* Table Layout + * Positions children into columns and rows +* Constraint Layout + * Allows children to specify their position relative to their parent view +* Scroll View + * A vertical scrolling view; only contains a single element + +###### Views Widgets + +* Views that the user can optionally interact with + * Buttons, text view, calendar viewer, image viewer, etc. +* Generate UI events + +###### Views Parameters + +* width or height + * Use percentages - relative to parent or screen width, etc. +* ID + * Used to generate a Java member variable we can refer to within the program +* Basic binding of methods + * Used to automatically bind UI events to methods + +###### Views Resources + +* Layouts are an example of a *resource* + * Static content used by components at run-time + * Can be referenced by ID + +Data Binding - involves a lot of boilerplate code + +`@{}` notation - receives data changes + +`@={}` - receives data changes to the property and listens to user updates + +##### Model-View-ViewModel + +![img](img/l.png) + +## The Manifest + +A *list* of the application's components diff --git a/docs/lectures/mdp/04_threads.md b/docs/lectures/mdp/04_threads.md new file mode 100644 index 0000000..383d9b1 --- /dev/null +++ b/docs/lectures/mdp/04_threads.md @@ -0,0 +1,78 @@ +# Threads (and Services) + +Activities are regularly transitioned to the background + +* i.e. when they are stopped or destroyed +* As the user continues with the *task* + +### Thread of Execution + +Android applications use a **single thread model** + +* A single thread of execution called *main* + * Started when a *process* is created +* Handles and dispatches user interface events + * Drawing the interface, responding to `onClick()` +* Handles activity life cycle events + * `onCreate()`, `onDestroy()` + * For all components in an application + +### Looper and Handler + +`HandlerThread` - extension of thread with support for looper + +**Looper** + +* Each `HandlerThread` can have one looper +* A Java thread dies when the run method returns +* Maintains a message queue +* `looper.loop()` - loops through the message queue and processes waiting messages + +**Message** + +* A task to be completed + * Might contain data or a reference to a `Runnable` object + +**Handler** + +* Attached to a looper +* Enqueues messages in the looper message queue +* Handles messages from the message queue +* **Thread-safe** +* One looper can have many handlers associated with it + +![img](img/m.png) + +If we run code that takes >5 s, the application will appear to hang. + +* Put longer-running / non-instantaneous code in a separate thread of execution + * Network access, file access +* 2 rules + 1. Do not block the UI thread + 2. Do not access the UI thread from outside the UI thread + - Android view objects are not thread-safe + - *Post* messages via the Handler to the UI thread's looper + +We can programmatically interact with UI components + +- e.g. `textField.setText(string)` +- But cannot call this method from outside the UI thread (rule 2) + +Instead, split code into two parts + +1. Long(ish)-running code that *does not* involve the UI +2. Instantaneous code that *does* involve the UI + - Which needs to be posted to the UI thread responsible for the view + +We need to remember the activity life-cycle; otherwise, we risk having **orphaned threads**. + +#### AsyncTask and others + +###### Accessing the UI thread from another thread + +```java +Activity.runOnUiThread(Runnable); +View.post(Runnable); +View.postDelayed(Runnable, long); +MutableLiveData.postValue; +``` \ No newline at end of file diff --git a/docs/lectures/mdp/05_services.md b/docs/lectures/mdp/05_services.md new file mode 100644 index 0000000..1018421 --- /dev/null +++ b/docs/lectures/mdp/05_services.md @@ -0,0 +1,130 @@ +# Services + +### Uses of services + +- MP3 Playback + - Playing songs in the background +- Network Access + - Long downloads, sending emails, polling an email server for new mail, etc. + +### Services + +An application **component** that + +- Has no UI +- Represents a desire to perform a longer-running operation + +Activities are loaded and unloaded as users move around the app + +- Services remain for as long as they are needed +- One service may be used by many other applications to avoid duplication of resources. + +### What are Services *not*? + +**Not** a separate process - runs in the same process as the application in which it is declared + +**Not** a thread - there's one thread per application + +Services are simple + +- It's a way of telling the system about a part of your app that is expected to run for a long time + - i.e. longer than a few seconds + +### Tasks, Services and Activities + +###### Email + +- Checks for new mail occasionally -> Service +- Collects new mail and stores it -> Service +- Notifies user that there is new mail -> Service / Activity + - New component - **notifications** +- User switches to inbox and retrieves/views new mail -> Activity + +###### MP3 Playback task + +- Play music while user does something else -> Service +- Create a playlist -> Activity +- Change the song playing & display current song progress -> Service / Activity + +### Creating a Service + +- Services are designed to support communication with + - Local activities (in the same process) + - within VM + - Remote activities + - IPC (Inter-process communication) + - Multiple components + - providing a service for multiple clients + +Services are components, similar to an activity + +- Register the service in the manifest +- Create a subclass of `android.app.Service` +- Handle the relevant life cycle methods + +### Service Life Cycle + +- By nature, services are **singleton objects** + - A service might be used by many clients +- A service is started by something + - via an `intent` + - The service subclass object is instantiated if necessary + - `onCreate()` is called + - either `onStartCommand` or `onBind` will be called depending on how the service has been invoked +- `onCreate()`/`onStart()`/`onBind()` are called in the context of the main UI thread + - A single thread for all components in an application + - Must spawn a worker thread +- Something calls `stopService()` + - Could be the service, one of the clients (the activity) or the OS +- `onDestroy()` + +## Code Examples + +`MainActivity` class + +```java +public class MainActivity extends AppCompatActivity { + @Override + protected void onCreate(Bundle ...) { + ... + } + + //if clicked twice - onStartCommand is called, onCreate is called ONCE + public void onClickStartService(View v){ + this.startService(new Intent(MainActivity.this, SimpleService.class)); + } + + public void onClickStopService(View v){ + this.stopService(new Intent(MainActivity.this, SimpleService.class)); + } + + public void onClickClobberService(View v) { + android.os.Process.killProcess(android.os.Process.myPid()); + } +} +``` + +`SimpleService` class + +```java +public class SimpleService extends Service { + //called first + public void onCreate() { + super.onCreate(); + } + + //called second + public int onStartCommand(Intent i, int flags, int startId) { + return Service.START_REDELIVER_INTENT; + } +} +``` + +Android Manifest + +```xml + + +``` diff --git a/docs/lectures/mdp/06_communication.md b/docs/lectures/mdp/06_communication.md new file mode 100644 index 0000000..1a7acf8 --- /dev/null +++ b/docs/lectures/mdp/06_communication.md @@ -0,0 +1,206 @@ +# Services - Communication + +How can an **activity** communicate with a **service**? + +> By sending one or more intents +> +> - This is done by calling `onStartCommand` multiple times + +How should the **service communicate** with the **user**? + +> This is done through notifications + +How should the **service** **communicate** with the **activity**? + +> For example: sending an email or playing an MP3 +> +> For this we use **binding** + +How does the **service** guarantee that **work is completed**? + +> By using life-cycles + +## Notifications + +**Notifications** are intended to inform users about events from an application. + +- Potentially a source of disruption. + - Caused by something in the background + - Require the user's attention + - Adversely affect task completion time (of the user) + - Impact the emotional & effective state of the user + +### Cross-Platform Principles + +###### Avoid + +- An app the user has never opened +- Messages that encourage the user to return to an app, but provide no value +- Operations that don't require user involvement, like syncing information +- Error states from which the app could recover without user interaction +- Personal/sensitive/confidential information + +###### Aim To + +- Create succinct, easy-to-read notifications that provide useful information +- Provide intuitive, beneficial actions + +###### Actioned via + +- Showing a status bar icon +- Appearing on the lock screen +- Playing a sound/vibration +- Peeking onto the current screen + +### Relationship to Services + +- Notify the user that the service is operating / has done something + - Service does not have a UI + - The notification is an invitation for the user to return to the application + - This is because the original activity might not still be running +- Notifications are maintained by the service + - Can specify an activity to launch if the user taps on it via a `PendingIntent` + - 'return' to the activity that spawned the service + - A `PendingIntent` itself is simply a reference to a token maintained by the system describing the original data used to retrieve it. This means that even if the owning application's process has been killed, the `PendingIntent` itself will remain usable from other processes that have been given it. + - Can control the service via buttons in the notification + - Deliver Intents to the service (`startService`/`onStartCommand`), this works because the service is a singleton object + +### Activity/Service Navigation and State + +###### Ways back to the activity + +- Via service hosted notification +- Via task manager +- Via launcher + +###### Depending on the owning process, the activity might have been + +- Destroyed +- Finished + +###### The activity is ephemeral (lasting a short amount of time) + +- Incorrect to store server state in activity instance state + - What has the service been doing in the meantime? +- Interrogate service to retrieve non-instance state `onCreate`, `onBind` +- Start or stop the service (is it still necessary/needed) + +## Service Lifecycle + +Two ways of spawning a service + +- Started (loosely coupled) + - Send an intent to explicitly start the service with `startService()` + - Will run/exist in the background indefinitely / kills itself + - Useful for consistently checking emails + - **Does not return a result** + - Explicitly stop the service with `stopService()` +- Bound (tightly coupled) + - Bind to a service using `bindService()` + - Will run while activities are bound to it + - Provides a programmatic interface for activities to communicate with the service + +In both cases, if the service is not running, it will be created. + +- Different responsibilities for the lifecycle + - If I start it, I have to stop it + - If the OS starts it, the OS stops it when it decides to +- Two conflated purposes + - *Manage* the service lifecycle + - *Bind* to the service for communication + - *Only* Bind = automatic lifecycle + - *Only* Start = manual lifecycle, intent communication + - Start *and* Bind = manual lifecycle, programmatic interface + +![img](img/n.png) + +### Terminating Services + +A service runs in the background indefinitely + +- Even if the component that started it is destroyed / finished + +Termination of service + +- Self-termination (calling `stopSelf()`) +- `stopService()` via an intent +- System termination + - i.e. memory storage + +Avoiding termination + +- Foregrounding a service + - This is something the user should really know about or is aware of + - Is treated as important as a foreground activity, `startForeground()` +- Background services are vulnerable + - In Android 8.0+ - background services can and will be stopped by the system, enforcing a Cron / job scheduling model. + +A service runs in the background indefinitely + +- Indefinitely = a few minutes +- Even if the component that started it is destroyed +- `onStartCommand()` return value determines how the service should be continued if it is destroyed + +`START_NOT_STICKY` + +- After `onStartCommand()` returns, do not recreate the service unless there are intents to deliver + +`START_STICKY` + +- Recreate the service and call `onStartCommand()` again, but do not redeliver the last intent. + +`START_REDELIVER_INTENT` + +- Recreate the service and call `onStartCommand()` again; deliver the last intent + - Immediately resume the previous job, i.e. downloading a file + +## Foreground Services and Notifications + +Foreground services perform operations that are *noticeable* to the user + +- Foreground services are app processes that run in the background while the user is not directly interacting with the app. +- Android requires users to be made aware of this with a non-dismissible notification +- Because the user can't dismiss the notification, you should provide an action (button) for the user to stop the service. + +###### Examples + +- A music player app + - A notification will continually show song progress, play/pause, etc. + +## Communicating with Services + +Bind to the service + +- If not explicitly started, will be started by the OS +- Provide an interface for clients (Activities) to interact with a service + - Aims to be fast and stable +- Binder object asynchronously provides a reference to the service that we can call methods on + - via `ServiceConnection` + - Binder object forms the basis of the programmatic interface for **activities**. + - i.e. we can use this object to call methods on the service + - Asynchronous as we have to wait for the OS to create the service + +![img](img/p.png) + +| Activity | Service | +| :--------------------: | :-----: | +| Component | Service | +| Service Connection | IBinder | +| `onServiceConnected()` | | + +What this binder object allows us to do: + +We can use `ServiceConnection` to call methods on the service and receive results. + +### Activity/Service Communication + +- Extending the Binder class + - Return an interface via the `inBind()` method + - Only for a Service used by the same application + - Local services only + - Make method calls within the same JVM (Android runtime) +- Who drives communication? + - Activity - regularly polls the service for information + - Service + - Maintain a list of callbacks using Binder objects to identify activity clients + - Enumerate and call each activity via a callback interface diff --git a/docs/lectures/mdp/07_remotes.md b/docs/lectures/mdp/07_remotes.md new file mode 100644 index 0000000..cd5a6c8 --- /dev/null +++ b/docs/lectures/mdp/07_remotes.md @@ -0,0 +1,127 @@ +# Services - Remote + +There is no communication between the two virtual address spaces. + +![img](img/q.png) + +When a service is bound to, Android will inspect the intent and find the relevant component to instantiate. If it doesn't exist/isn't running, it will create it. The service object that's created will return a binder object. + +#### Remote Services + +Making objects appear as if they exist in the local process - abstraction + +- For communicating across process boundaries + - using a service belonging to a different application / process + - Handing off to **threads** in **different processes** + - Likely to be used by multiple processes at once + - Declare the service in the manifest + - Must not use implicit intents + - Doing something without the user's knowledge is problematic +- Examples like an MP3 player or location tracking do not need a remote service +- However, when using a service for downloading a file, multiple processes might want to use that and have access to progress. Another example is services that are drivers for hardware +- Communicating with it + - Using a messenger - preferred way ☑ + - Defining an interface + - Registering callbacks + - Wrapping a system service in an API + +#### Communicating with services + +##### Via Messenger + +What is a messenger? + +- An IPC for a service + - Message-based communication between processes + - Asynchronous - technically but *feels* sequential + - Messages with bundles of data as payload instead of method calls + - Queues messages into a single thread, which are handled sequentially + - Allows a service to define a handler + - 'Has' an `IBinder` that is shared with the client + - Passed to the client on service connection + - Used to send messages to the service +- Bi-directional communication + - The client can have a messenger too + - Provide a reference to the return messenger in our message + - Sending a binder over a binder + +#### Processes, Messengers and Handlers + +![img](img/a.jpg) + +##### Inter-process communication + +`java.io.Serializable` + +- Short-term persistence +- Write object ID and fields via reflection/introspection +- Brittle - If class/variable names are changed, it breaks +- It is slow + +`Parcelable` + +- Define a simple wire-protocol for writing primitives + - Re-create an object by passing salient data (deep copy) +- Immune to minor definition changes +- Supported by Android Kernel Driver +- Much faster + +```java +public int x = 5; +public int y = 6; +public String text = "Martin"; +// salient data is 5,6 & "Martin" + +public void writeToParcel(Parcel out, int flags) { + out.writeInt(this.x); + out.writeInt(this.y); + out.writeString(this.text); +} + +public void readFromParcel(Parcel in) { + this.x = in.readInt(); + this.y = in.readInt(); + this.text = in.readString(); +} +``` + +We can change the class definition, e.g. add a private attribute `z` that we don't wish to communicate. + +We can change the attribute names without anything breaking. + +### Defining Remote Interfaces + +Using the Android Interface Definition Language (AIDL) + +- Specify an interface for the service functionality +- Generates a proxy object + - To be used locally as if the remote service was not remote +- Generates a sub implementation + - The remote side of the transaction +- Generates a communication protocol + - Parcelling and un-parcelling steps - a wire protocol for copying and recreating an object. + +Similar to Java interface definitions + +- Label method parameters for efficiency + - **in**: transferred to the remote method + - **out**: returned to the caller + - **inout**: both in and out + - **oneway**: asynchronous +- Permitted types + - Java primitive type: Lists, Maps, Other AIDL generated interfaces + - Classes implementing the Parcelable protocol + +![img](img/r.png) + +AIDL allows us to define something more complicated than just messages. + +We define an interface, the IDE then generates a proxy object and a stub object, and also figures out how those two will communicate + +We can then use calls on the proxy, which will delegate those calls into the stub object. We are responsible for implementing the methods in the stub object + +### Binder abstraction + +![img](img/s.png) + +The binder driver can receive messages from multiple processes, so the service has to reason about receiving them diff --git a/docs/lectures/mdp/08_binders.md b/docs/lectures/mdp/08_binders.md new file mode 100644 index 0000000..47fae51 --- /dev/null +++ b/docs/lectures/mdp/08_binders.md @@ -0,0 +1,166 @@ +# Binder Principles + +### IPC - Inter-process communication + +An API for IPC does not exist; however, a communication paradigm between separate process components that everything uses at some level does exist + +- Each process has its own address space + - Provides data isolation + - Prevents direct interaction between different processes +- We have to use **binders** for communication + - Binder is fundamentally a kernel driver + - Provides lightweight remote procedure calls (RPC) + - Reading and writing parcels between processes + - Per-process **thread pools** for handling requests + - **Synchronous** calls between processes + +![img](img/g.png) + +Note: binder is a kernel driver + +##### Ideal IPC + +![img](img/t.png) + +This is an idealised abstraction + +##### Binder as Intermediary + +![img](img/u.png) + +The client asks the binder driver to do something; it'll then use one of its threads to talk to the service. It needs a thread pool, as if another client makes a request, it needs to be handled sequentially. + +All communication is mediated by the binder driver. This is possible because of the privileged position of the kernel in an operating system, e.g. access to kernel space. + +#### Binder Facilities + +###### Calls + +- Simple inter-process messaging system +- one-way or two-way + +###### Identifying + +- Via PID or UID (user ID) +- This is down to the privileged position of the kernel + - Cannot be deceived as it has access to all memory + +###### Notification + +- Link to death + - Leaked service connections + +###### Managing + +- Reference counting +- Object mapping across processes +- Sleeping and waking worker threads + +###### Indirect Functionality + +- Can use a binder object as a globally unique token +- Sharing a file descriptor to shared memory + +#### Binder Implementation + +- API for apps + - AIDL + - Java API Wrapper + - Exposes the IBinder interface + - Wraps the middleware layer + - Parcelable object marshalling interface +- Native Middleware + - Implements the user space (within a process) facilities of the Binder framework + - Marshalling and un-marshalling of specific data to primitives + - Provides interaction with the Binder kernel driver +- Kernel Driver + - Supports ioctl (input/output system controls) from middleware + - Supports cross-process file operations, memory mapping + - Thread pool for each service application for IPC + - Mapping of objects between processes via `copy_from_user`, `copy_to_user` + +![img](img/v.png) + +`/dev/binder` - appears as a device, as it's a driver + +### Binder Transactions + +The proxy binder will call `IBinder.transact()` and then the binder driver will call `Binder.onTransact()` on the stub + +![img](img/w.png) + +Binder maintains a pool of transaction threads in each process + +- To dispatch all IPC coming from other processes + +- If process A calls process B + + > - Calling thread in A blocks in `transact()` + > - Sends the transaction to process B + > - Next available thread in process B receives the incoming transaction, calls `onTransact()` on the target object, replies with the resultant parcel + > - Thread in process A returns, resumes execution + +- Reliant on Service B responding in a timely manner + + - Hence catching remote exceptions & transaction failures + - Developer-defined worker threads + - Handling multiple calls from multiple transaction threads + +Proxy object that's making the `transact` call and the stub object that makes the `onTransact()` call. + +![img](img/s.png) + +#### IPC Abstractions + +###### Intent + +- Highest-level abstraction +- Asynchronous message passing + - Messenger + +###### Inter-process method invocation + +- AIDL + +###### Binder + +- Kernel Driver + +![img](img/x.png) + +### Binder Security + +Binder doesn't deal with security + +- Enables a **trusted** execution environment +- Transactions via the kernel + - Client identity is managed by the kernel + - `Binder.getCallingUid()`, `Binder.getCallingPid()` +- Access controlled in two ways: + 1. Limit who can obtain a reference to a binder object + - Interface reference security + - Client cannot guess *address* of a service + - The binder driver *knows* who has knowledge of which objects + 2. Check caller identity before performing an action on the binder objects + - Service asks package number manager about UID permissions + - Check whether it holds a permission we want to enforce via `PackageManager.getPackageInfo(...)` + +### Binder Performance + +###### Explicit limitations + +- Transactional buffer size 1 Mb per process for all concurrent transactions in a process + - Many moderately sized transactions could exhaust its limit + - Arguments and return values are too large + - Keep transaction data small + +###### Implicit Limitation + +- Data is copied + - Duplication of memory resources +- Native binary marshalling + - Better than reflection-based serialisation + - Still has overhead of parcel marshalling +- Not ideal for large data streams + - You wouldn't want to pass videos through bundles + - Instead, we pass file descriptors to shared memory regions \ No newline at end of file diff --git a/docs/lectures/mdp/09_system_services.md b/docs/lectures/mdp/09_system_services.md new file mode 100644 index 0000000..95ebc0f --- /dev/null +++ b/docs/lectures/mdp/09_system_services.md @@ -0,0 +1,108 @@ +# System Services + +There are many system services + +- Activity Manager +- Notification Manager +- Location Manager +- … + +###### `onPause()` + +![img](img/y.png) + +All the communication is facilitated by `Binder`. + +### System services and APIs + +##### Power Management + +- Lock the device in *awake* power mode +- Only allow this app to unlock this operation + +```java +public class MainActivity extends Activity { + + private PowerManager.WakeLock wakeLock; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + PowerManager pm = + (PowerManager) getSystemService(Context.POWER_SERVICE); + wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag"); + wakeLock.acquire(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + wakeLock.release(); + } +} +``` + +- Connect to the service (Power Manager) +- Create a unique token + - This unlocks the phone, can be passed to other components + +This is what actually happens: + +![img](img/z.png) + +#### Binder Objects and Tokens + +###### Binder Object + +- An object that can be accessed through the binder framework + - When connected to a service, we're given a binder object back which we use as a proxy for accessing the service. +- Implements the `IBinder` interface +- A unique identity maintained across processes + - **Allocated by the binder driver** + - Cannot be duplicated. Binder objects maintain a unique ID even when parcelled + - Is a 32-bit ID maintained by the kernel + +Process A creates a binder object <- references memory directly + +> (really asks the Binder driver to allocate it a Binder object for the local object) +> +> Passes it to process B <- referenced by handle (ID) +> +> - Can then be passed to process C the same way + +###### Capability-Based security model + +Processes are granted access to a particular resource by giving them a *capability* in the form of the binder object + +- Binder object as **token** + +The possession of a token grants the owning process full access to the Binder object, enabling it to perform Binder transactions on the target object. + +- The only way to communicate with a Binder object is to be given a reference to it + +### Service Manager + +A single context manager that maintains references to (system service) Binder objects + +- Implemented as a `ServiceManager` + - Also hosts many system services within its process + - As the system user. Not root, but a privileged user +- A Binder instance with a known binder handle (`ID=0`) +- Knows about other remote services + - The first to be registered with the Binder + - Only *trusted* system services allowed to register + - System, radio, media +- Binder submits a service name and its Binder handle to the `ServiceManager` via IPC + - Client retrieves remote service Binder handle with service name + - Client communicates with remote service + +When wanting to make use of the power manager, I ask the service manager for the binder handle for that particular service. + +This means the kernel does not reason about security; however, the service manager does. + +![img](img/aa.png) + +![img](img/ab.png) + + diff --git a/docs/lectures/mdp/10_storage.md b/docs/lectures/mdp/10_storage.md new file mode 100644 index 0000000..efe04a0 --- /dev/null +++ b/docs/lectures/mdp/10_storage.md @@ -0,0 +1,240 @@ +# Storage + +### Storage Principles + +#### App-Specific Requirements + +- Store files that are meant for our use only +- Store files that we intend to share with other apps + - e.g. taking a photo +- Store private, primitive data + - Config data, passwords, cookies & keys, etc. +- Store private, structured data + - text messages + +#### Mobile Storage Principles + +- Efficiency and sharing vs privacy and security + - Limited storage capacity + - Highly personal information stored + - Lots of different data types stored on phone +- Media + - Images, videos, music + +> Access to the mail should be protected since this is sensitive user data. However, if a reference to an image attachment is given to an image viewer, that image viewer will not have permission to open the attachment since it has no reason to hold a permission to access all e-mail. + +##### Storage Directories + +`/system` -> stores Android OS & libraries + +`/data` -> where user data is stored (every application is a user) + +`/mnt/sdcard` (symlinked as `sdcard`) -> *External* Storage + +### Basic Logical Data Storage on Android + +##### Different Volumes + +###### Internal + +- Limited space for app-specific data +- Reliable (not *removable*) +- Soldered RAM + +###### External + +- Lots of data +- May (or may not) be physically removable + +##### Different kinds of data + +- Data that is only meaningful for our app should use app-specific storage +- Shareable media content should use shared storage so that other apps can access the content + - Also called scoped storage + +##### File-based abstractions + +- Shared preferences +- File-based storage +- SQLite database + - Structured data, small binary blobs + +![image-20220107004129910](img/ac.png) + +## Internal File Storage + +Internal data storage is private to the app + +- Other apps (and the user) cannot access it + - Kernel-enforced user perms +- Removed on uninstall +- Data is stored in files + - `/data/data/com.example.project/files/` + - Full path not accessible; `files/` becomes the chroot + - This ensures we cannot traverse the directory upwards and gain access to other applications' files + +##### Cache Files + +`/data/data/com.example.project/cache` + +`getCacheDir()` -> gets application’s file directory + +Programmer should manage the files + +- **May** be deleted when internal storage becomes full +- **Will** be deleted when application is uninstalled +- A *well-behaved* application will delete them when no longer in use +- Recommended to use less than 1MB + +#### Shared Preferences + +- Stored on a per-application basis + - e.g. saving config info (settings) + - Should not be used for data transfer (use intents and binders instead) +- Primitive data in key-value pairs +- Can have multiple preference files per application + +```xml + + + light + +``` + +```java +SharedPreferences settings = getSharedPreferences(CONFIG_STORAGE_NAME, 0); +SharedPreferences.Editor editor = settings.editor; + +if (settings.getBoolean(MainActivity.CONFIG_THEME, false)) + setTheme(...); +else + ... +``` + + + +#### External Storage + +*Legacy name* + +- Every Android device provides externally accessible storage (SD card) + - Even phones without a physical SD card must have a **logical representation** of external storage + - Most phones will have one storage device partitioned into `internal / external` + - Phones must do this to conform to the Android API + - *Private* Application files + - *Internal* storage on the external partition + - `getExternalFilesDir()` + - `/sdcard/Android/data/com.example.project/` + - *Public* general files + - World reachable + - Other apps can read and modify these files + - Each *user* has their own *virtual* SD card +- Can be mounted externally (and unmounted/disconnected) + +##### Getting Access to External Storage + +- Should check state with `Enviroment.getExternalStorageState()` + - It is a separate file system, potentially removable + - `Environment.MEDIA_MOUNTED` + - `Environment.MEDIA_MOUNTED_READ_ONLY` +- Use `getExternalStoragePublicDirectory (String type)` to obtain file for the directory + - Media is stored by type + - Music in the music dir, etc. + - Pass a type to obtain the subdirectory for that type + +##### Getting Scoped storage access + +- To access files that other apps have created + - We must have `READ_EXTERNAL_STORAGE` permission (in the manifest) + - With this one permission, the app can do whatever (look at downloads, listen to music, look at pictures, etc.) + - This is where scoped storage comes into play + - The files must reside in the media collection (images/music/videos, etc.) + - or request legacy storage `MANAGE_EXTERNAL_STORAGE` (before Android 11) +- Apps only have access to + - App-specific directory on external storage + - Specific types of media that the app has created and contributed to well-defined collections + - If the app takes a picture, it is allowed to store and look at that picture but not allowed to access pictures not taken by that app + - You don't need to request perms to read/write images that we are writing to the MediaStorage + +# Android Databases + +When the data stored is logically structured, queries are needed to find it based on the structure. + +- Android provides local database support + - Can run full SQL queries +- Each app’s databases are local to it + - `Database.db` stored in internal storage +- Powered by SQLite + +#### Android and SQLite + +- Wrapped in two main classes + - Database represented by `SQLiteDatabase` object + - Allows us to run SQL queries on the database + - `SQLiteOpenHelper` + - Supports the application lifecycle + - `SQLiteOpenHelper` -> `onCreate()` + - Creates the database the **first time** it is called + - This database will exist until the application is installed + - `SQLiteOpenHelper` -> `onUpdate(int oldVer, int newVer)` + - Changing the version number allows the database to be dropped and recreated +- Create an instance of our `SQLiteOpenHelper` subclass +- Get reference to `SQLiteDatabase` using + - `getReadableDatabase()` + - `getWriteableDatabase()` + +##### Querying a Database + +`void execSQL()` -> used to execute SQL queries that don't return anything + +`query()` and `rawQuery()` + +- These return a Cursor object pointing to the results + +`Cursor rawQuery (String sql, String[] selectionArgs)` + +###### Cursors + +- Provide random access to results of a query +- Enable us to enumerate the rows returned by the query + - `moveToFirst()`, `moveToNext()` + - `getString(colIndex)`, `getInt(colIndex)` +- Have a `close()` method to close the query when finished + +We can pass cursors to other applications + +###### CursorLoader + +- A query may last some time + - Database may be large + - May be in a different process + - Don’t block the main thread +- `CursorLoader` + - Populates views asynchronously + - Auto-updating + +(deprecated) + +#### Data-Driven Views + +- *Connect* a cursor to a `CursorAdapter` and a `ListView` + - Think mapping rows of a database to which entry in the list + - Each row must have an ID field +- `RecyclerView` + - An optimised, flexible version of the above + - Only creates views for visible data + - As the user scrolls, more data is added + - We can define our own adaptor + +### Database Abstraction + +Abstraction of database architecture + +- Easier to update storage code +- Expose column indices as static class variables + - `c.getInt(0)` ✗ + - `c.getInt(DBHelper.NAME)` ✓ +- Helper methods keep database internals from *leaking* into other classes + - Return a collection of results rather than the cursor +- **Sanitise user inputs** + - SQL injections still apply diff --git a/docs/lectures/mdp/11_room_mvvm.md b/docs/lectures/mdp/11_room_mvvm.md new file mode 100644 index 0000000..d085b43 --- /dev/null +++ b/docs/lectures/mdp/11_room_mvvm.md @@ -0,0 +1,199 @@ +# Room and MVVM + +## ROOM + +### Room Persistence Library + +- An architecture component +- A database layer on top of SQLite + - Takes care of tasks that `SQLiteHelper` dealt with + - Like compile-time validation of SQL queries + - Allows us to think about objects with fields rather than tables with rows + +#### Room Components + +![image-20220107154928136](img/ad.png) + +###### Database + +- Contains a database holder +- A singleton serves as the main access point to persistent data + +###### Entities + +- Java classes that represent (or become) tables in the database + +###### DAO + +- Data Access Object (software design pattern) +- An abstract interface for accessing the database to retrieve a given entity + +#### Database + +An abstract class that + +- Is annotated with `@Database` +- Extends `RoomDatabase` +- Lists the entities associated with the database +- Includes abstract methods that return DAO interfaces for the entities + +Is generally implemented as a **singleton** to retrieve a reference to the database with the application context + +- Returned by `RoomDatabase.databaseBuilder` + +A more structured approach to the database lifecycle + +- `onCreate`, `onOpen`, `onDestructiveMigration` +- When the database schema is modified, we must define a migration strategy + +Room **does not** support database access on the main thread + +- Queries could take a while, so they shouldn’t be done on the main/UI thread + +#### Entity + +- Plain old Java class + - Represents a table in the underlying database + - Sets of related fields +- Annotated to describe how to think about it in terms of the database + - Needs to have a `@PrimaryKey` + - Field names become column names, unless we annotate an alternate + - `@ColumnInfo(name = 'my_column_name')` + - `@Ignore` certain fields +- Embedded entities, 1-to-1 or 1-to-many relationships + - `@Embedded`, `@Relation`, `@Transaction` + +#### DAOs + +- Interface / Abstract class + - Common practice to have one DAO per entity +- Implementation is created at compile time + +Specify convenience queries, annotated to tell Room what to do + +- `@Insert` generates an implementation that inserts all parameters into the database in a single transaction. +- `@Update` updates a set of entities given as parameters using a query that matches against the primary key of each entity. + - If the entity is updated, it will update the underlying SQL database +- `@Query` read/write operations as something like a conventional database query. +- `@Delete` removes entities given as parameters. + +### MVVM Architecture + +![image-20220107160502350](img/ae.png) + +VIEW (UI controller) is the V + +ViewModel is the current state of the data needed to populate the view + +Room is the model; it is all the data for the entire application + +ViewModel $\subset$ (is a subset of) Room Database + +NOTE: Room is just the database manager, others exist. + +Repository - as far as the view model is concerned, it asks the repository for all data. It abstracts access to different possible back-ends. The view model doesn’t need to know how the data is stored, e.g. whether data is stored on `data/.cache` or on a web server `ftp://192.168.0.5`. + +The repository is responsible for connecting to the website and downloading data into cache to support functionality when the internet drops out. + +**All view models** get their data from the **same repository** + +# Coding Example + +```java +import androidx.room.Entity + +@Entity(tableName = "myTable") +public class Record { + + @PrimaryKey + @NonNull + @ColumnInfo(name = "name") // only needed if they don't match + + public Record(@NonNull String name, String colour) { + this.name = name; + ... + } +} +``` + +Interface DAO + +```java +//Can be an abstract class or interface +//Room will generate the implementation based on this + +import androidx.room.Doa; + +@Dao +public interface RecordDao { + @Insert + void insert (Record r); + + @Insert(onConflict = OnConflictStrategy.IGNORE) + void insertLots (Record... r); + + @Query("DELETE FROM myTable") + void deleteALl(); + + @Query("SELECT * FROM myTable ORDER BY name ASC") + List getAlphaRecord(); + + @Query("SELECT * FROM myTable") + LiveData> getAlphaRecord(); + //LiveData is lifecycle aware +} +``` + +Boilerplate database stuff + +```java +import androidx.room.RoomDatabase; + +@Database(entities = {Record.class}, version=1, exportScheme=false) +public abstract class myDatabase extends RoomDatabase { + + public abstract RecordDao(); + + private static volatile myDatabase INSTANCE; + + //as we're not allowed to query on the main thread + static final ExecutorService dbWriter = Executors.newFixedThreadPool(4); + + //context needed to know file path + static myDatabase getDatabse(final Context context) { + + if (INSTANCE == null) { + synchronised (myDatabase.class) { + INSTANCE = Room.databaseBuilder( + context.getApplicationContext(), + myDatabase.class, "myDatabase") + .fallbackToDestructiveMigration() + .build(); + } + + } + } +} +``` + +Main Activity + +```java +public class MainActivity extends .. { + + myDatabase db; + RecordDao rDao; + + protected onCreate (...){ + db = myDatabase(getApplicationContext()); + rDao = db.recordDao(); + } + + public void addNewRecord(){ + myDatabase.dbWriter.execute(() -> { + Record r = new Record ("data", "data"); + rDao.insert(r); + }) + } +} +``` diff --git a/docs/lectures/mdp/12_content_providers.md b/docs/lectures/mdp/12_content_providers.md new file mode 100644 index 0000000..fd8b59e --- /dev/null +++ b/docs/lectures/mdp/12_content_providers.md @@ -0,0 +1,164 @@ +# Content Providers - Storage + +Access to data is restricted to the app that owns it + +- Database is usually located in internal app-specific storage +- If we want other apps to access our data, or we want to access other apps’ data, or we want to be notified when data has changed, we must use a content provider + +Content providers expose data / content to other applications in a structured manner + +- Fundamentally IPC via Binder and ashmem (Android shared memory) with a well-defined (database-like) interface + +#### System Content Providers + +Content providers manage data for: + +**Browser**: bookmarks, history + +**Call Log**: Telephone usage + +**Contacts**: Contact data, contacts for other apps, e.g. WhatsApp + +**Media**: Media metadata database + +**User Dictionary**: database for predictive spelling + +###### Storage Access Framework + +Is an abstraction of *documents* + +- Restricted access to external storage + - Enumerated by the system content object picker + +![image-20220107180058110](img/af.png) + +A content provider is mostly used for making content available outside your application, as using it to get data is now done by the repository. + +###### How to use it? + +- Create our own by sub-classing `ContentProvider` + - Must add it in the manifest +- Or add/query data via an existing content provider + +### Data Model + +Very similar to a relational database table + +- A collection of records +- Support for read/write +- Support for typical database operations + - CRUD - **C**reate **R**ead **U**pdate **D**elete + +Records are stored in rows, with each column providing different data fields + +- Each record has a numeric id (in the field ID) that uniquely identifies it +- Tables exposed via URI + - This is a further abstraction + +![image-20220107180837589](img/ag.png) + +Applications query the content provider, which maps the requests to the underlying database. This can be SQLite or Room (doesn’t really matter to the application) + +### Querying a Content Provider + +Content Providers **identify data** sets through **URIs** + +- `content://authority/path/id` +- **content**: Data managed by a content provider +- **authority**: ID for the Content provider + - A fully qualified class name, e.g. `com.example.project` +- **path**: 0 or more segments indicating the subset of data to be requested + - e.g. table name + - A RESTful resource philosophy +- **id**: specific record (row) being accessed + +`/email/2021/Nov/17` -> would retrieve all emails received on Nov 17th 📅 + +###### Content Resolver + +- Manages and supports content provider access +- How to service a request for content + - Similar to `ServiceManager` +- Enables Content Providers to be used across multiple applications +- Can observe a content provider to be informed of real-time modifications + - e.g. `contentResolver` monitors the path and can notify if a new email pops up ✉ + +Full URI: `ContactsContract.Contact.CONTENT_URI = "content://com.android.contacts/contacts/"` + +`ContentResolver.query(...)` + +- Returns a cursor instance for accessing results +- Cursor is a pointer to a `cursorWindow` + - A read-only reference to shared memory + - Allocated by ashmem + - Retrieved via Binder +- Max `CursorWindow` size is 2 Mb + +###### Example of Querying Contacts + +- To access / modify requires a permission + - `android.permission.READ_CONTACTS` + - `android.permission.WRITE_CONTACTS` +- Contacts has 3 components + - Data + - Rows (mime-typed) that can hold personal info + - Raw Contacts + - A contact for a given person from a given system + - Gmail contact, Facebook contact, etc. + - Associated with data entries + - Contacts + - Aggregated raw contacts + - Single view of a *person* + +##### Modifying a Content Provider + +`Uri insert (Uri uri, ContentValues values)` + +Returns the URI of the newly inserted item + +`int update(Uri uri, ContentValues values, String where, String[] selectionArgs)` + +###### Parameters + +**uri**: the *table* we want to modify + +**content values**: values for the new row or key/value pairs where the key is the column name + +#### Creating a content Provider + +- Implement a storage system for the data + - Structured data, can be SQLite or Room + - Media & blobs +- Implement a content provider + - query, add, update, insert, etc. + - onCreate + - When content provider is instantiated, needs to instantiate the internal storage (create the table) + - getType + - single items, multiple items, mime type +- Tell Android we are a provider + - Declare in the manifest + +#### Contract + +- Defines metadata pertaining to the provider +- Constant definitions that are exposed to developers via a compiled .jar file + - Authority + - URI + - Meta-data + - Column names + +#### URI Matching + +All of these methods take a URI as the first parameter + +- The object will need to parse it to know what to return + +`android.content.UriMatcher` + +- Provides mapping between abstraction of contract class to concrete db implementation +- Does the calling app want all the data from the table or just a row? + - `content://authority/tablename/` + - whole table + - `content://authority/tablename/1` + - row + - Or a virtual table (joins across various underlying resources) diff --git a/docs/lectures/mdp/13_broadcasts.md b/docs/lectures/mdp/13_broadcasts.md new file mode 100644 index 0000000..fdb27ac --- /dev/null +++ b/docs/lectures/mdp/13_broadcasts.md @@ -0,0 +1,142 @@ +# Broadcast Receivers + +It is the 4th component in Android + +1. Activity + - User interface +2. Service + - Performs a long-running background task +3. Content Provider + - Storage and provision of data +4. Broadcast receivers + +Components are *entry points* + +###### Event-based + +Respond to system-wide broadcast announcements + +- The user has not necessarily done something, but the OS / phone / another application has + - e.g. the screen has turned off, battery is low, phone booted, new text +- Can be sent by an application, or received by an application from the OS +- Create the process, instantiate a `BroadcastReceiver` + +**Intents** are sent to **specific activities** + +- Explicitly or implicitly via intent filters + +**Broadcasts** are sent to **anything** that cares to listen + +- System-wide intent broadcasts + +### Broadcasts + +- Broadcasts are intents + - Send an intent to start an activity or service +- Send an intent to trigger broadcast receivers that subscribe to that particular class of intent + - Can define our own broadcast intents + - Cannot send system intents (battery, screen, etc.), as the security model prevents it + - Uses binder for messaging + +![image-20220107185728288](img/ah.png) + +#### Broadcast Receiver + +- Must be registered + + - Either in the manifest or context-registered + - **Context-registered** -> runtime + - To receive events while running + +- Declare in manifest + + ```xml + + + + + + ``` + +- Specify broadcast intents we are interested in + + - Receiver is registered at boot-time / install-time / run-time (context) + +##### Implementation + +- Sub-class `BroadcastReceiver` + - Specify which intents we are interested in +- Implement the `onReceive()` method +- Send a message to our application to change our behaviour + - Reduce the volume when a notification comes through +- Start an activity + - **Do not start activities** from broadcast receivers (jarring for user) +- Start a service + - A gateway to another component, e.g. start polling for emails +- Show a notification + - Alert the user that there is something that they need to interact with at *some point* + +### Normal and Ordered Broadcasts + +`sendBroadcast(intent)` - intent can be implicit or explicit + +`sendOrderedBroadcast(intent, receiverPermission)` + +`sendOrderedBroadcast(intent, receiverPermission, resultReceiver)` + +Receive data back from the broadcast, `resultReceiver` will be treated as a final receiver at the end of the broadcast. + +Ordered broadcasts are received by the highest-priority receivers first + +Preferred receivers are given the chance to consume the broadcast before it is delivered to less preferred receivers + +#### Sticky Broadcast + +**Non-Sticky** - if you weren’t listening at the time, you’ve missed it + +**Sticky** intents are cached by Android + +- These are so much slower than just implementing direct calls within your own app IPC for each receiver to register. They will also incur a massive IPC overhead + +Sticky broadcasts are **deprecated** + +#### Local Broadcasts + +Data broadcast will not leave the application + +Other apps cannot send broadcasts to our application + +- More efficient than sending a global broadcast + - No IPC + +**Now deprecated** due to the MVVM architecture + +#### Context-registered Receivers + +Can no longer use a manifest-declared receiver for most implicit broadcasts + +- Broadcasts that don’t target our app specifically + +We can receive broadcasts as long as their registered context is valid + +- If we register it in `onCreate`, we should *unregister* in `onDestroy` to prevent leaking the receiver + +#### Broadcasts in practice + +The application receiving the broadcasts must have been explicitly started / not explicitly stopped + +- Applications cannot intercept broadcasts without the user having some awareness that they have given it permission + +Either the sender or receiver of a broadcast can implement permissions + +##### Lifecycle + +Process is aggressively killed once `onReceive()` has returned + +- Long-running code should be in a service instead +- `goAsync()` + - Can be called in `onReceive()` to keep the broadcast active after returning from that function + - ~10 seconds to do something + + + diff --git a/docs/lectures/mdp/14_touch_tech.md b/docs/lectures/mdp/14_touch_tech.md new file mode 100644 index 0000000..0084700 --- /dev/null +++ b/docs/lectures/mdp/14_touch_tech.md @@ -0,0 +1,192 @@ +# Touch Technology + +#### Resistive Touch Screen + +- Two sheets of transparent layers with metallic (resistive) coating facing each other with a thin gap in between + +![image-20220117192647424](img/ba.png) + +![image-20220117192702751](img/bb.png) + +![image-20220117192716222](img/bc.png) + +- Can be used with a finger or any pointing device (passive) +- Requires a certain amount of pressure (to get the resistance to register) +- Can be modified for multi-touch (only two touches) +- Has high tolerance for liquids and contaminants + - They're still used in hospitals and industry where fluids have a high spill rate + +#### Surface Capacitive Touch Screen + +- Screen is covered in a capacitive material + - This is 90% transparent +- Capacitance - ability to store electrical charge (this works through glass) +- We apply a small voltage to generate an electrostatic field +- Humans naturally act as small capacitors; touching the screen with a finger creates a dynamic capacitor. +- Measure the effective capacitance at each corner of the screen + - The larger the change, the closer to the corner the touch was + - Combine these measurements from all corners to find the exact location of the touch + +![image-20220117193603738](img/bd.png) + +Using the distance from all 4 corners to determine the location. This only actually needs 3 corners; the 4th is used for accuracy. + +##### Projected (Mutual) Capacitance + +For multi-touch, there is a grid of sensors. + +![image-20220117204813192](img/be.png) + +- Conductive material is etched with rows & columns +- An electric field is projected through the top layer of the glass +- A human acts as a conductor; a decrease in capacitance between electrodes is detected as a touch + +The 1st-generation iPhone had a 10 x 15 (150) grid of sensors. + +To get a higher resolution: + +![image-20220117205050223](img/bf.png) + +Similarly, we can do this with multiple touches + +![image-20220117205141036](img/bg.png) + +#### 3D touch + +- Pressure-sensitive touch +- This involves flexible glass + - Pressing forces the finger closer to the rear capacitor + - We can use this to measure depth, not location + +# Gestures + +Gesture - A series of touch events that occur over a period of time + +`TouchBegin()`, `TouchMoved()`, `TouchEnded()` + +Two ways to register these: + +1. Implement `onTouchEvent()` in an activity +2. Register a new `OnTouchListener` with a view - `setOnTouchListener(...)` + +One or more fingers on the screen will trigger the callbacks of `onTouchEvent()` on the view. + +Either way, the detailed interactions are delivered using a `MotionEvents` object + +#### MotionEvent + +This object encapsulates information about: + +- Touch events + - A touch begins (`ACTION_DOWN`) + - The finger moves (`ACTION_MOVE`) + - The touch ends (`ACTION_UP`) +- (x,y) coordinates of the touch, information about pressure, size, orientation, etc. +- Additional information for multi-touch, e.g. pointer ID, action index, etc. + +###### ACTION_DOWN + +- A gesture starts when a finger is pressed +- A `MotionEvent` is generated for this +- Find the action by calling `getAction()` +- This can also have the identifier of the *pointer*, so use `getActionMasked()` for multi-touch + +###### ACTION_MOVE + +- As the finger moves, a series of ACTION_MOVE events will be sent +- Find the new position using `getX()` and `getY()` (returns floats) +- Note that Android bundles these into a series of touch events, so we can get historic touches + +###### ACTION_UP + +- A gesture ends in three ways + 1. `ACTION_UP` - last finger has been taken off the display + 2. `ACTION_CANCEL` event - another event happens, cancelling the gesture, e.g. the phone rings + 3. `ACTION_OUTSIDE` event - if the finger moves outside the relevant view + +### Single Touch Gesture + +Formed of: + +1. A single `ACTION_DOWN` +2. Zero or more `ACTION_MOVE` +3. An `ACTION_UP` to finish + +#### Single-touch interactions + +- Positions are tracked to move an object +- Use movement velocity for a swipe / fling + +#### Dragging & Scrolling + +- Store the original (x,y) touch location from ACTION_DOWN +- Calculate changes from stored value and value returned from `ACTION_MOVE` or `ACTION_UP` +- Adding the coordinate changes to the original object location + +#### Swipe / Fling + +- Rather than moving the object, we can calculate the velocity and direction +- On `ACTION_UP`, continue to move the object with that velocity +- Gives the user obvious visual feedback of *flinging* UI elements across the screen + +#### Customised Gestures + +Several different ways of tracking the movement of a gesture + +- Use the starting and ending point of a pointer +- Use the direction the pointer is travelling +- Use velocity of the pointer +- Use `getHistorical` to get historical movements + +### Multi-touch Gestures + +- Very similar to single touch +- Same sequence of events with a few more events + - `ACTION_POINTER_DOWN` & `ACTION_POINTER_UP` + - Support for 256 touches at the same time + +##### Determining Finger + +- **Index**: position within the array in a `MotionEvent` +- **ID**: Unique for each pointer (finger) to allow tracking an individual pointer across the entire gesture +- The number of pointers can change as fingers are lifted or placed; so do the indices of the pointers +- Each pointer is given an ID that won’t change + - Need to track both the ID and past locations of pointers to move things about + +![image-20220117212640923](img/bh.png) + +`onTouchEvent` and `motionEvent` + +- `onTouchEvent` is a callback method +- `motionEvent` is an object that contains gesture information +- When a user places fingers on the screen, it triggers the callback `onTouchEvent()` on the view +- After some touch actions, the `motionEvent` delivered to `onTouchEvent()` provides the details of every interaction + +```java +public boolean onTouchEvent(MotionEvent event) { + ... + int maskedAction = event.getActionMasked(); + switch (maskedAction) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_POINTER_DOWN: + case MotionEvent.ACTION_MOVE: + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_POINTER_UP: + case MotionEvent.ACTION_CANCEL: +} +``` + +#### Pinch to zoom + +- Obtain the IDs of the two pointers + - Use this to get the index so we can get locations +- Calculate and store the distance between the two pointers +- The ratio of the new distance to the old one gives the zoom / scale ratio + +#### Two-finger rotation + +- Obtain the IDs of the two pointers + - Use this to get the index so we can get locations +- Use the vertical and horizontal location difference to calculate the initial angle +- Obtain the new locations of the two pointers to derive the new angle +- Object can be rotated using the difference in angles \ No newline at end of file diff --git a/docs/lectures/mdp/15_power_management.md b/docs/lectures/mdp/15_power_management.md new file mode 100644 index 0000000..26f5712 --- /dev/null +++ b/docs/lectures/mdp/15_power_management.md @@ -0,0 +1,286 @@ +# Power Management + +#### Power Saving + +- Knowledge about the power consumption of each component and app +- Screen / Network / CPU off or release other device resources as soon as not needed +- Limit resources for less frequently used apps +- Set device to sleep as soon as there are no user interactions +- Global management of running jobs across all apps + - Perform syncs, uploads & downloads together in a fixed time window + +#### Battery Consumption Statistics + +- Framework tracks the time that devices spend in different states + - e.g. WiFi chip-set: on/off + - Display: low/high brightness +- Controlling service **pushes** state changes to `BatteryStats` service +- Framework **pulls** the data at these transition points +- App power consumption is calculated based on CPU run time at specific speeds + +#### Android Power Management Concept + +- **G0** - working +- **G1** - sleeping + - **S1** - CPU stops executing instructions, power to CPU and RAM maintained + - **S2** - CPU powered off, cache is flushed + - **S3** - Standby / sleep / suspend power to RAM + - **S4** - Hibernate, suspend disk, RAM powered off +- **G2** (S5) - soft off +- **G3** - mechanical off + +#### Power Management Design + +- A wrapper to Linux Power Management +- Added to the Kernel + - Wake lock mechanism +- Apps need to request the CPU & screen to be on with `WakeLocks`; otherwise, Android will shut down the CPU +- Wake locks and timeouts constantly switch the state of the system’s power + - Overall system power consumption decreases + - *Better* use of battery capacity + +![image-20220117221604007](img/ca.png) + +### WAKE_LOCK + +Firstly, request the WAKE_LOCK permission in the manifest + +```xml + +``` + +Use `newWakeLock()` to create a `PowerManager.WakeLock` object + +```java +PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); +PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag"); +wl.acquire(); +..screen will stay on during this section.. +wl.release(); +``` + +| Flag Value | CPU | Screen | Keyboard | +| :------------------------ | :------------------------------------------------- | ------ | -------- | +| `PARTIAL_WAKE_LOCK` | On (Don’t sleep even when power button is pressed) | Off | Off | +| `SCREEN_DIM_WAKE_LOCK` | On | Dim | Off | +| `SCREEN_BRIGHT_WAKE_LOCK` | On | Bright | Off | +| `FULL_WAKE_LOCK` | On | Bright | Bright | + +> Creating and holding wake locks can have a **dramatic impact** on the host device's battery life. Thus you should use wake locks only when **strictly necessary** and hold them for as **short a time as possible**. +> +> - If app is performing long-running HTTP downloads, consider `DownloadManager` +> - If app is synchronising data, consider sync adapter +> - If your app relies on background services, consider `JobScheduler` to trigger services at specific intervals +> - One use case for wake lock might be a background service that needs to grab a wake lock to keep the CPU running to do work while the screen is off. + +#### Battery Life Enhancement in Android 6.0+ + +##### App Standby + +Defer background activity for apps with no recent user interaction + +###### Start Conditions: + +An app that is not actively used for a certain time will be placed in an idle mode + +- Not doing foreground work (activities, services, pending intents, notifications) +- Hasn’t been explicitly launched for a certain time (can be days) + +###### Actions + +- No network access +- No background jobs +- Can set alarms +- Can use wake locks +- Is allowed network access once per day + +###### Exit conditions + +- When the device is plugged in + - Notice when your phone is plugged in, the screen will stay on for longer +- When a foreground task is performed by the user + +##### Doze + +A deep sleep if the user has not actively used the device for extended periods of time + +###### Starts Doze + +- When device is idle, screen is off, on battery & stationary + +###### In doze + +- No network access +- No CPU-intensive work +- Wake locks ignored +- No Wi-Fi scan +- Deferred alarm manager alarms +- Only high-priority notifications received +- No job scheduler +- No sync adaptors + +###### Exits Doze + +- User interaction +- Device motion +- Screen on +- Alarm clock alarm +- Notifications **do not** cause Doze exit + +###### Maintenance windows + +Maintenance windows complete pending activities (syncs, jobs, etc.) + +- SMS & Telephony services are **excluded** from Doze. + +![image-20220117223601872](img/cb.png) + +##### Exemptions + +System apps and cloud messaging services pre-loaded on the phone are exempt from App Standby and Doze + +Uses whitelist for apps to be partially exempt from Doze & App standby + +- `isIgnoringBatterOptimizations()` to check if it's in the whitelist +- `ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS` intent to redirect user to battery optimisation options +- `REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` allow user to add app to white-list directly +- White-listed apps can use network and hold partial wake locks during Doze and App standby, but jobs and syncs are still deferred +- The app should not be on the whitelist unless it cannot use Firebase Cloud Messaging, high-priority messages or the app’s core functionality is affected. + +#### App Stand-By Buckets + +Prioritise apps based on how recently and how frequently the apps are used + +- Active: currently or recently used +- Working set: regular use +- Frequent: often used but not every day +- Rare: not frequently +- Never: never + +#### Firebase Cloud Messaging + +Replaced Google Cloud Messaging + +- A cross-platform reliable battery-efficient messaging solution that allows messages to be delivered between the server and client. +- Provides a single and persistent connection to the server. +- Can notify a client app that a new email or other data is available to sync +- Can deliver to single device, groups of devices or devices subscribed to topics. +- Send messages from client apps to the server (e.g. chats, messages, etc.) + +#### Sustained Performance Mode + +- Thermal throttling prevents long-running apps from maintaining their performance (e.g. games, cameras, VR, etc.) +- App can request to enter SPM, and keep a consistent level of performance + - Set using `Window.setSustainedPerformanceMode()` +- System automatically disables the mode when no longer in focus + +# Power 2 + +**Background processes** + +- Threads +- Services +- `AsyncTasks` +- `AlarmManager` + - Based on time +- `JobScheduler` + - Based on conditions +- `WorkManager` + - Requires Google Play service + - Automatic use of `alarmManager` and `jobScheduler` + +The bottom three will guarantee completion when we are not worried about when it will happen + +#### Alarm Manager + +- Schedule a task to run at a specific time point or time interval +- `AlarmManager` holds a CPU wake lock, when the `onReceive()` method is executing +- Alarm manager operates outside of your application, so it can be used to trigger events when the app is not running or the device is asleep. +- Alarm delivery is inexact + - Use `setWindow` and `setExact` for exact delivery + +##### Usage + +- Specify an intent to be broadcast at some time + - `setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)` + - `setExact(int type, long triggerAtMillis, PendingIntent operation)` +- Extend Broadcast receiver + - `onReceive` method is called when the alarm goes off + - Start a service to actually do the work + +#### Job Scheduler + +- Many apps perform tasks asynchronously outside the main activity (downloading files) +- Job Scheduler collects pending jobs across all apps and schedules them to run at about the same time, so that the phone can sleep for longer and save more power +- Specify requirements for network and timing for each job, then the JS robustly optimises the execution time. +- May defer jobs that comply with Doze and App StandBy +- `JobService` **will run on the main thread**; you need to manage any asynchronous tasks yourself (using threads) + +##### Usage + +- Construct `JobInfo` objects using `JobInfo.Builder` using schedule conditions + - Network type (metered/unmetered) + - Charging and Idle + - Content Provider update + - Back-off (retry) criteria + - Minimum latency and override deadline + - Periodic + - Persistent + - Extras (customised information from app) +- Pass it to `JobScheduler` using *schedule* (`JobInfo`) +- Jobs implemented in the app’s `JobService` +- Jobs will be executed (batch & defer jobs smartly) at a certain time, but not an exact time (minimum period length is 15 minutes for periodic jobs) + +#### Work Manager + +- Guaranteed but deferrable +- Supports one-off or periodic tasks +- Queryable - check if work is successful +- Chainable: Job 2 is dependent on the execution of job 1 +- Opportunistic: do the background work as soon as it can + +##### When to use work manager + +✓ Upload media to a server + +✓ Parse data and store it in a database + +✓ Periodically sync local data with the network + +✗ Extract paint colour and update image views (use thread pools) + +✗ Parse data and update contents of a View (use thread pools) + +✗ Process payment transactions (use a foreground service) + +##### Usage + +- Add dependencies + +```groovy +dependencies { +implementation "androidx.work:work-runtime:$versions.work" +} +``` + +- Work Request + +```java +mWorkManager = WorkManager.getInstance(application); +mWorkManager.enqueue(OneTimeWorkRequest.from(Worker.class)); +``` + +- Chain workers + +```java +WorkContinuation continuation = mWorkManager.beginWith(workA); +continuation.then(workB).then(workC).enqueue(); +``` + +- Set constraint + +```java +Constraints constraints = new Constraints.Builder() + .setReuiresCharging(false) + .build(); +``` diff --git a/docs/lectures/mdp/16_app_testing.md b/docs/lectures/mdp/16_app_testing.md new file mode 100644 index 0000000..ca0503f --- /dev/null +++ b/docs/lectures/mdp/16_app_testing.md @@ -0,0 +1,82 @@ +# App Optimisation, Testing & Deployment + +### Check Memory Usage + +- `abd shell dumpsys meminfo ` + - Check if memory size increased since launch + - Number of objects that have been created + - Database information +- Terminology: + - Native Heap: memory used by the process itself + - Dalvik Heap: memory allocated by DalvikVM + - Dalvik Other: memory used for JIT + - Pss total: all connections to the main device memory thread + - Private dirty: actual amount of RAM the app is using on the heap since the app started + +### Code Optimisation + +- Minimise object creation +- Make a method static if there is no need to modify the state of an object +- Make any constants `static final` +- `Int` is 2x faster than `float` +- Use enhanced for loops (for-each instead of regular for loops) + +### App Testing + +![image-20220118165511824](img/cc.png) + +- Generally, developing tests is done before developing code + +#### Unit Tests + +- Build unit tests to verify the logic of specific code in the app +- Local tests + - run on the local Java VM +- Instrumented tests + - run based on the Android dependencies + - Can use `mockito` or `robolectric` to isolate a unit from its dependencies + +#### UI Tests + +- Test an entire sequence of events, user interface, end-to-end testing on emulators & devices + +- Tools: `AndroidJUnitRunner` & `Espresso API` & UI Automator + +- Modify `build.gradle` + + ```groovy + dependencies{ + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + } + ``` + +- Espresso records UI interactions and can use these to run a repeatable test automatically + +#### Monkey (stress test) + +- Runs on an emulator and generates pseudo-random streams of user events (clicks, touches, gestures and system-level events) + +```sh +$ adb shell monkey [options] +$ adb shell monkey -p your.package.name -v 500 +``` + +#### APK Generation + +- Use a good / unique *package name* + - `[org/com].[company].[product].[component]` +- Build `->` Generate Signed APK + +##### Shrink Code & Resources (Proguard) + +```groovy +buildTypes { + release { + minifyEnable true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } +} +``` + +Can try `proguard-android-optimize.txt` for more code shrinking \ No newline at end of file diff --git a/docs/lectures/mdp/17_cross_app_dev.md b/docs/lectures/mdp/17_cross_app_dev.md new file mode 100644 index 0000000..5132892 --- /dev/null +++ b/docs/lectures/mdp/17_cross_app_dev.md @@ -0,0 +1,84 @@ +# iOS and Cross-Platform Development + +![image-20220118173020092](img/cd.png) + +| | Android | iOS | +| -------------------- | :-------------------------: | :---------------------------: | +| Market Share | 82% | 13.9% | +| Programming Lang | Java
Kotlin | Objective-C
Swift (2014) | +| IDE | Eclipse
Android Studio | Xcode | +| OS | Windows/Mac/Linux | Only on Mac! | +| Distribution Process | Release can take hours | Release can take weeks | +| Fees | \$24 one-off | \$99 per year | + +### iOS + +- Based heavily on Mac OS X +- Closed source + - Tools, deployment, app ecosystem controlled by Apple +- Apps can only be installed from the App Store + - Cryptographically signed + - Apple runs App Store + - Approves all apps available from it + +#### iOS Apps + +- Written in Objective-C & Swift + - An extension of C to add support for objects + - Using the Cocoa Touch UI framework + - Can also use C/C++ libraries + - Compiles to native code via LLVM (not interpreted (JIT) as on Android) + +##### Structure of an App + +**M**odel **V**iew **C**ontroller Design Pattern + +![image-20220118174042986](img/ce.png) + +**UI Application Object**: manages event loop & high-level app behaviour + +**Application Delegate**: Handles app initialisation and state transitions + +**Data Objects**: Store data for the app (images, database, etc.) + +**Document**: Manage data objects + +**View Controller**: Manages the presentation of the app on the screen, loads views, shows views, rotates views, etc. + +**UI Window**: Coordinates the presentation of one or more views on a screen + +**Views & UI objects**: Draw content, buttons, etc. + +##### iOS Lifecycle + +- Apps are sandboxed; inter-app communication is used to pass data +- Only one application in the foreground / visible at once +- A main loop processes events for the application + - Xcode creates the main function +- App can be in a number of significant states + - Active: foreground + - Inactive: foreground but interrupted + - Background: same as services in Android + - Suspended: main loop no longer running; remains in memory but is potentially killed by the operating system + +##### State Transitions + +![image-20220118175629095](img/cf.png) + +![image-20220118175733832](img/cg.png) + +![image-20220118180929130](img/da.png) + +#### App Store + +- Pre-moderation + - Apple checks all applications in advance manually + - Versus Android: publish and then revoke +- A long list of guidelines as to what is appropriate + +## Cross-platform + +#### Xamarin + +- Developed by Microsoft +- `xamarin.Forms` for native UI code diff --git a/docs/lectures/mdp/18_revision.md b/docs/lectures/mdp/18_revision.md new file mode 100644 index 0000000..c5b8d45 --- /dev/null +++ b/docs/lectures/mdp/18_revision.md @@ -0,0 +1,26 @@ +# Revision + +### Exam + +- 24 hours + - Meant to take around 1 hour +- Marked out of 45 +- Answer **all** questions + +##### Knowledge + +- Bookwork, recall of factual information + - State, provide +- Not many of these, as the exam is open-book + +##### Comprehension + +(demonstrate understanding) + +- Students are asked to perform actions like + - Describe, explain, classify ideas/concepts + - In your own words + +##### Application + +- Undertake an *unseen* task by using knowledge in a new way diff --git a/docs/lectures/mdp/img/a.jpg b/docs/lectures/mdp/img/a.jpg new file mode 100644 index 0000000..077cb16 Binary files /dev/null and b/docs/lectures/mdp/img/a.jpg differ diff --git a/docs/lectures/mdp/img/a.png b/docs/lectures/mdp/img/a.png new file mode 100644 index 0000000..349d9f4 Binary files /dev/null and b/docs/lectures/mdp/img/a.png differ diff --git a/docs/lectures/mdp/img/aa.png b/docs/lectures/mdp/img/aa.png new file mode 100644 index 0000000..fc80e06 Binary files /dev/null and b/docs/lectures/mdp/img/aa.png differ diff --git a/docs/lectures/mdp/img/ab.png b/docs/lectures/mdp/img/ab.png new file mode 100644 index 0000000..30662ae Binary files /dev/null and b/docs/lectures/mdp/img/ab.png differ diff --git a/docs/lectures/mdp/img/ac.png b/docs/lectures/mdp/img/ac.png new file mode 100644 index 0000000..c829eec Binary files /dev/null and b/docs/lectures/mdp/img/ac.png differ diff --git a/docs/lectures/mdp/img/ad.png b/docs/lectures/mdp/img/ad.png new file mode 100644 index 0000000..3878ec2 Binary files /dev/null and b/docs/lectures/mdp/img/ad.png differ diff --git a/docs/lectures/mdp/img/ae.png b/docs/lectures/mdp/img/ae.png new file mode 100644 index 0000000..eb945de Binary files /dev/null and b/docs/lectures/mdp/img/ae.png differ diff --git a/docs/lectures/mdp/img/af.png b/docs/lectures/mdp/img/af.png new file mode 100644 index 0000000..078afdd Binary files /dev/null and b/docs/lectures/mdp/img/af.png differ diff --git a/docs/lectures/mdp/img/ag.png b/docs/lectures/mdp/img/ag.png new file mode 100644 index 0000000..df9c528 Binary files /dev/null and b/docs/lectures/mdp/img/ag.png differ diff --git a/docs/lectures/mdp/img/ah.png b/docs/lectures/mdp/img/ah.png new file mode 100644 index 0000000..b3d7aa5 Binary files /dev/null and b/docs/lectures/mdp/img/ah.png differ diff --git a/docs/lectures/mdp/img/b.png b/docs/lectures/mdp/img/b.png new file mode 100644 index 0000000..9a64af6 Binary files /dev/null and b/docs/lectures/mdp/img/b.png differ diff --git a/docs/lectures/mdp/img/ba.png b/docs/lectures/mdp/img/ba.png new file mode 100644 index 0000000..7b24d88 Binary files /dev/null and b/docs/lectures/mdp/img/ba.png differ diff --git a/docs/lectures/mdp/img/bb.png b/docs/lectures/mdp/img/bb.png new file mode 100644 index 0000000..778403a Binary files /dev/null and b/docs/lectures/mdp/img/bb.png differ diff --git a/docs/lectures/mdp/img/bc.png b/docs/lectures/mdp/img/bc.png new file mode 100644 index 0000000..adac9aa Binary files /dev/null and b/docs/lectures/mdp/img/bc.png differ diff --git a/docs/lectures/mdp/img/bd.png b/docs/lectures/mdp/img/bd.png new file mode 100644 index 0000000..2f286c7 Binary files /dev/null and b/docs/lectures/mdp/img/bd.png differ diff --git a/docs/lectures/mdp/img/be.png b/docs/lectures/mdp/img/be.png new file mode 100644 index 0000000..45d5133 Binary files /dev/null and b/docs/lectures/mdp/img/be.png differ diff --git a/docs/lectures/mdp/img/bf.png b/docs/lectures/mdp/img/bf.png new file mode 100644 index 0000000..1853be6 Binary files /dev/null and b/docs/lectures/mdp/img/bf.png differ diff --git a/docs/lectures/mdp/img/bg.png b/docs/lectures/mdp/img/bg.png new file mode 100644 index 0000000..745ed8a Binary files /dev/null and b/docs/lectures/mdp/img/bg.png differ diff --git a/docs/lectures/mdp/img/bh.png b/docs/lectures/mdp/img/bh.png new file mode 100644 index 0000000..9d9b4af Binary files /dev/null and b/docs/lectures/mdp/img/bh.png differ diff --git a/docs/lectures/mdp/img/c.png b/docs/lectures/mdp/img/c.png new file mode 100644 index 0000000..56640b4 Binary files /dev/null and b/docs/lectures/mdp/img/c.png differ diff --git a/docs/lectures/mdp/img/ca.png b/docs/lectures/mdp/img/ca.png new file mode 100644 index 0000000..b93caf7 Binary files /dev/null and b/docs/lectures/mdp/img/ca.png differ diff --git a/docs/lectures/mdp/img/cb.png b/docs/lectures/mdp/img/cb.png new file mode 100644 index 0000000..11d2b43 Binary files /dev/null and b/docs/lectures/mdp/img/cb.png differ diff --git a/docs/lectures/mdp/img/cc.png b/docs/lectures/mdp/img/cc.png new file mode 100644 index 0000000..89ad41f Binary files /dev/null and b/docs/lectures/mdp/img/cc.png differ diff --git a/docs/lectures/mdp/img/cd.png b/docs/lectures/mdp/img/cd.png new file mode 100644 index 0000000..4f02927 Binary files /dev/null and b/docs/lectures/mdp/img/cd.png differ diff --git a/docs/lectures/mdp/img/ce.png b/docs/lectures/mdp/img/ce.png new file mode 100644 index 0000000..00a8bb8 Binary files /dev/null and b/docs/lectures/mdp/img/ce.png differ diff --git a/docs/lectures/mdp/img/cf.png b/docs/lectures/mdp/img/cf.png new file mode 100644 index 0000000..9f853c2 Binary files /dev/null and b/docs/lectures/mdp/img/cf.png differ diff --git a/docs/lectures/mdp/img/cg.png b/docs/lectures/mdp/img/cg.png new file mode 100644 index 0000000..d173745 Binary files /dev/null and b/docs/lectures/mdp/img/cg.png differ diff --git a/docs/lectures/mdp/img/d.png b/docs/lectures/mdp/img/d.png new file mode 100644 index 0000000..e4f8c6f Binary files /dev/null and b/docs/lectures/mdp/img/d.png differ diff --git a/docs/lectures/mdp/img/da.png b/docs/lectures/mdp/img/da.png new file mode 100644 index 0000000..50df389 Binary files /dev/null and b/docs/lectures/mdp/img/da.png differ diff --git a/docs/lectures/mdp/img/e.png b/docs/lectures/mdp/img/e.png new file mode 100644 index 0000000..985ccbe Binary files /dev/null and b/docs/lectures/mdp/img/e.png differ diff --git a/docs/lectures/mdp/img/f.png b/docs/lectures/mdp/img/f.png new file mode 100644 index 0000000..39df0a9 Binary files /dev/null and b/docs/lectures/mdp/img/f.png differ diff --git a/docs/lectures/mdp/img/g.png b/docs/lectures/mdp/img/g.png new file mode 100644 index 0000000..f6d1d1c Binary files /dev/null and b/docs/lectures/mdp/img/g.png differ diff --git a/docs/lectures/mdp/img/h.png b/docs/lectures/mdp/img/h.png new file mode 100644 index 0000000..e223418 Binary files /dev/null and b/docs/lectures/mdp/img/h.png differ diff --git a/docs/lectures/mdp/img/i.png b/docs/lectures/mdp/img/i.png new file mode 100644 index 0000000..cd0c7c7 Binary files /dev/null and b/docs/lectures/mdp/img/i.png differ diff --git a/docs/lectures/mdp/img/j.png b/docs/lectures/mdp/img/j.png new file mode 100644 index 0000000..2cb54fd Binary files /dev/null and b/docs/lectures/mdp/img/j.png differ diff --git a/docs/lectures/mdp/img/k.png b/docs/lectures/mdp/img/k.png new file mode 100644 index 0000000..db4ddff Binary files /dev/null and b/docs/lectures/mdp/img/k.png differ diff --git a/docs/lectures/mdp/img/l.png b/docs/lectures/mdp/img/l.png new file mode 100644 index 0000000..400e516 Binary files /dev/null and b/docs/lectures/mdp/img/l.png differ diff --git a/docs/lectures/mdp/img/m.png b/docs/lectures/mdp/img/m.png new file mode 100644 index 0000000..76f9bcb Binary files /dev/null and b/docs/lectures/mdp/img/m.png differ diff --git a/docs/lectures/mdp/img/n.png b/docs/lectures/mdp/img/n.png new file mode 100644 index 0000000..d9b8560 Binary files /dev/null and b/docs/lectures/mdp/img/n.png differ diff --git a/docs/lectures/mdp/img/p.png b/docs/lectures/mdp/img/p.png new file mode 100644 index 0000000..8382c89 Binary files /dev/null and b/docs/lectures/mdp/img/p.png differ diff --git a/docs/lectures/mdp/img/q.png b/docs/lectures/mdp/img/q.png new file mode 100644 index 0000000..1776eaa Binary files /dev/null and b/docs/lectures/mdp/img/q.png differ diff --git a/docs/lectures/mdp/img/r.png b/docs/lectures/mdp/img/r.png new file mode 100644 index 0000000..1094436 Binary files /dev/null and b/docs/lectures/mdp/img/r.png differ diff --git a/docs/lectures/mdp/img/s.png b/docs/lectures/mdp/img/s.png new file mode 100644 index 0000000..2a7a723 Binary files /dev/null and b/docs/lectures/mdp/img/s.png differ diff --git a/docs/lectures/mdp/img/t.png b/docs/lectures/mdp/img/t.png new file mode 100644 index 0000000..8ec2efb Binary files /dev/null and b/docs/lectures/mdp/img/t.png differ diff --git a/docs/lectures/mdp/img/u.png b/docs/lectures/mdp/img/u.png new file mode 100644 index 0000000..d788fb6 Binary files /dev/null and b/docs/lectures/mdp/img/u.png differ diff --git a/docs/lectures/mdp/img/v.png b/docs/lectures/mdp/img/v.png new file mode 100644 index 0000000..7752ae6 Binary files /dev/null and b/docs/lectures/mdp/img/v.png differ diff --git a/docs/lectures/mdp/img/w.png b/docs/lectures/mdp/img/w.png new file mode 100644 index 0000000..8c7f72b Binary files /dev/null and b/docs/lectures/mdp/img/w.png differ diff --git a/docs/lectures/mdp/img/x.png b/docs/lectures/mdp/img/x.png new file mode 100644 index 0000000..da01b80 Binary files /dev/null and b/docs/lectures/mdp/img/x.png differ diff --git a/docs/lectures/mdp/img/y.png b/docs/lectures/mdp/img/y.png new file mode 100644 index 0000000..4e5b310 Binary files /dev/null and b/docs/lectures/mdp/img/y.png differ diff --git a/docs/lectures/mdp/img/z.png b/docs/lectures/mdp/img/z.png new file mode 100644 index 0000000..711fdb3 Binary files /dev/null and b/docs/lectures/mdp/img/z.png differ diff --git a/docs/lectures/mdp/practice_tests.md b/docs/lectures/mdp/practice_tests.md new file mode 100644 index 0000000..09fa554 --- /dev/null +++ b/docs/lectures/mdp/practice_tests.md @@ -0,0 +1,203 @@ +# Practice Test + +## 2018-19 + +### Question 1 + +#### a) + +**Describe the concept of System on a Chip and Package-on-Package** + +- System on a chip is where the chip is divided into multiple regions, each of which deals with a different task, and is built block by block from descriptions of separate parts. +- Package-on-package is where different components are stacked on top of one another to save space + +#### b) + +**Describe the concept of ARM big.LITTLE and ARM Thumb** + +- The ARM processor contains a low-performance and a high-performance core. These two cores are architecturally consistent, so the system can switch between the two as appropriate for the task. +- ARM Thumb is a 16-bit-long ARM instruction set; these Thumb instructions can run 2 instructions in parallel, as registers in the processor are 32 bits. + +#### c) + +**Android applications run in an implementation of the Java virtual machine** + +##### i. + +**Java virtual machine (VM) is stack-based and the Dalvik VM is register-based. List an advantage and a disadvantage of the register-based VM compared to the stack-based VM.** + +Stack-based often has shorter instructions, whereas register-based has fewer instructions to execute and is optimised to use less space. + +##### ii. + +**Describe the role of the Zygote process as part of Dalvik and how it aims to make efficient use of memory.** + +Zygote initialises all the processes that use core libraries, loads all Java and Android classes and creates the Android VM process. + +##### iii. + +**Dalvik has been replaced by Android Runtime (ART) from Android version 5.0. Dalvik uses a trace-based just-in-time compiler. State the type of compiler that ART uses.** + +##### iv. + +**State an advantage and a disadvantage of ART over Dalvik.** + +#### d) + +**The Android operating system was developed based on Linux kernels. Describe three Android-specific modifications to the Linux kernel.** + +1. Wake locks have been added to keep the phone awake in certain situations +2. Binders were added to facilitate inter-process communication, so that apps can communicate with other apps +3. ashmem was added for shared memory between apps +4. oom was added to save memory resources when memory is low +5. alarm manager was added to add alarm functionality and to wake the phone when necessary + +### Question 2 + +#### a) + +**The projected capacitive screens support multiple point touches. Explain the working principle behind the multiple touches** + +For multi-touch functionality, there is a grid of capacitance sensors. These are arranged in rows and columns, and when a finger is pressed against the glass, the sensors record a decrease in capacitance and register a touch. + +If multiple sensors record a drop in capacitance, it is registered as multiple touches. + +#### b) + +**Explain how a high-resolution touch can be achieved based on the grid of electrodes** + +High-resolution touch can be achieved without adding more sensors. When a touch is registered by one sensor, the surrounding sensors will register a smaller drop in capacitance. By summing these drops and taking the average, a more accurate location can be found. + +#### c) + +```java +@Overrides +public boolean onTouchEvent(MotionEvent event) { + int maskedAction = event.getActionMasked(); + + switch (maskedAction) + { + case MotionEvent.ACTION_DOWN: + int finger1 = event.getPointerID(); + float f1x_start = event.getX(finger1); + float f1y_start = event.getY(finger1); + break; + case MotionEvent.ACTION_POINTER_DOWN: + int finger2 = event.getPointerID(); + float f2x_start = event.getX(finger2); + float f2y_start = event.getY(finger2); + break; + case MotionEvent.ACTION_MOVE: + break; + case MotionEvent.ACTION_UP: + float f1x_end = event.getX(finger1); + float f1y_end = event.getY(finger1); + float f2x_end = event.getX(finger2); + float f2y_end = event.getY(finger2); + } + + init_ang = 180 - Math.arctan(f2x_start - f1x_start / + f2y_start - f1y_start); + + end_ang = 180 - Math.arctan(f2x_end - f1x_end / + f2y_end - f1y_end); + + rotation_ang = init_ang - end_ang +} +``` + +### Question 3 + +#### a) + +**State when it would be appropriate to use a Service component in an Android application, specifically contrasting to the creation of a new thread within an Activity.** + +When the task is long and needs to happen independently of the app. + +#### b) + +**The *Proxy* design pattern is used to structure inter-process method invocation between a client and a remote service. In the context of an AIDL interface:** + +##### i. + +**Describe the role of the Proxy and Stub classes, providing the apparent use of each one, and describing how they make use of the system binder for communication.** + +##### ii. + +**Describe how the binder enables synchronous method calls between a client and a remote service** + +Binder is a kernel driver; this means it has access to kernel space in memory. When a client requests the binder driver, it uses a thread to speak to the service. + +##### iii. + +**State how communication with a remote service could be optimised by modifying the AIDL interface definition.** + +#### c) + +## 2016-17 + +### Question 1 + +#### a) + +**A simple Android application consists of two Activity components. The first, `MainActivity`, contains a String and an Integer. It also displays a button that, when pressed, launches `SecondActivity` via an explicit Intent. The user launches the application, then presses the button, and then presses the back button.** + +##### i. + +**Describe the life-cycle calls that these two Activities would receive, and in what order they would receive them. You should illustrate your answer with a diagram of the Activity stack as it changes over time.** + +``` +onCreate -> onStart -> onResume -> onPause -> onCreate -> onStart -> onResume -> onPause -> onResume +``` + +##### ii. + +**When the user is interacting with `SecondActivity`, the system becomes low on memory and decides that it should remove `MainActivity` to free up memory. State how this changes your answer to part (i). Describe how `MainActivity` should maintain its internal state during this process.** + +``` +onCreate -> onStart -> onResume -> onPause -> onCreate -> onStart -> onResume -> onDestroy +``` + +#### b) + +**An Activity can be started by a remote component using an implicit Intent. ==Describe== how an application could be integrated into a task using this method, and why it could be considered advantageous.** + +### Question 3 + +#### a) + +**One of the major drains on the battery of a mobile device is the 3G radio. A badly written application uses a started Service that persists in memory and regularly polls a remote website for updates. Explain how this might cause an increased drain on the battery, and describe how you might restructure the application’s components to preserve battery life.** + +This would drain the battery as the service would continually use the 3G radio to poll the web server. To improve this, Work Manager should be used. Work Manager would allow time windows for this to happen, which are synchronised with the other apps needing 3G. This means 3G does not need to stay on all of the time. + +- The service might keep the phone awake +- The question is about incorrectly doing stuff in the background + +#### b) + +**Android applications run in an implementation of the Java virtual machine Dalvik, or more recently the Android Runtime (ART).** + +##### i. + +**Describe the role of the Zygote process as part of Dalvik and how it aims to make efficient use of memory.** + +Zygote initialises all core libraries and loads all Java and Android classes. When a user runs an application, it creates a copy of a reference to itself in a separate address space. This way, all applications can use the same shared memory. + +##### ii. + +**State an advantage of ART over Dalvik.** + +- Apps run faster; bytecode is already translated to machine code during installation +- Reduces startup time of apps as native code is directly executed +- Improves battery performance as it produces more optimised code + +#### c) + +**The majority of modern Android devices make use of the ARM CPU core. State two advantages of using ARM in a mobile device, and describe one of the key differences of the RISC instruction set when compared to X86.** + +1. An ARM chip consumes less power than an x86 chip; this is especially useful in battery-powered phones +2. ARM chips are sold as a design and are more easily integrated onto a system on a chip, instead of buying a pre-bought Intel chip + +The RISC instruction set aims to complete each instruction set in one FDE cycle, whereas x86 instructions can take many cycles + + diff --git a/zensical.toml b/zensical.toml index 21ce8f2..0628f3b 100644 --- a/zensical.toml +++ b/zensical.toml @@ -167,6 +167,27 @@ nav = [ { "Anti-Virus" = "lectures/security/15_intrusion_detection.md" }, { "Cyber Threat Intelligence" = "lectures/security/16_cyber_threat_intelligence.md" }, ] }, + { "Mobile Development and Programming" = [ + { "Mobile Architecture" = "lectures/mdp/01_mobile_architeture.md" }, + { "Introduction to Android" = "lectures/mdp/02_android_os.md" }, + { "Activities" = "lectures/mdp/03_activities.md" }, + { "Threads" = "lectures/mdp/04_threads.md" }, + { "Services" = "lectures/mdp/05_services.md" }, + { "Communication" = "lectures/mdp/06_communication.md" }, + { "Remotes" = "lectures/mdp/07_remotes.md" }, + { "Binder Principles" = "lectures/mdp/08_binders.md" }, + { "System Services" = "lectures/mdp/09_system_services.md" }, + { "Storage" = "lectures/mdp/10_storage.md" }, + { "Room and MVVM" = "lectures/mdp/11_room_mvvm.md" }, + { "Content Providers" = "lectures/mdp/12_content_providers.md" }, + { "Broadcast Receivers" = "lectures/mdp/13_broadcasts.md" }, + { "Touch Technology" = "lectures/mdp/14_touch_tech.md" }, + { "Power Management" = "lectures/mdp/15_power_management.md" }, + { "App Optimisation, Testing & Deployment" = "lectures/mdp/16_app_testing.md" }, + { "iOS and Cross-Platform Development" = "lectures/mdp/17_cross_app_dev.md" }, + { "Revision" = "lectures/mdp/18_revision.md" }, + { "Practice Test" = "lectures/mdp/practice_tests.md" }, + ]} ] }, ]