├── Distribution.txt ├── PE_for_Android.keystore ├── PE_for_Android_whitepaper.pdf ├── README.md ├── addon-sys-img.xml ├── addon.xml ├── architecture.png └── howto ├── apps ├── apps.md ├── instant-run.png ├── policy-settings-1.png ├── policy-settings-2.png ├── policy.md ├── sdk-add-site.png ├── sdk-installed.png ├── sdk-path.png ├── sdk-project.md ├── sdk.md └── upal.md ├── phone └── installation.md └── platform └── platform.md /Distribution.txt: -------------------------------------------------------------------------------- 1 | Distribution Statement A. Approved for Public Release; Distribution Unlimited. 2 | 3 | Copyright © 2020 by Two Six Labs, LLC. 4 | 5 | This material is based upon work supported by DARPA and AFRL under Contract No. FA8750-16-C-0006. 6 | 7 | DISCLAIMER LANGUAGE 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 9 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 10 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 11 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 12 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 13 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 14 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 15 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 | -------------------------------------------------------------------------------- /PE_for_Android.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twosixlabs/PE_for_Android/bc4dc76ca1bb7953c2273b2bc12d1d12b8ba239c/PE_for_Android.keystore -------------------------------------------------------------------------------- /PE_for_Android_whitepaper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twosixlabs/PE_for_Android/bc4dc76ca1bb7953c2273b2bc12d1d12b8ba239c/PE_for_Android_whitepaper.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Privacy Enhancements for Android 2 | 3 | ## Overview 4 | 5 | Privacy Enhancements for Android (PE for Android) is a platform for exploring 6 | concepts in regulating access to private information on mobile devices. We 7 | developed PE for Android as a fork of the [Android Open Source Project 8 | (AOSP)](https://source.android.com) release for Android 9 "Pie." 9 | 10 | PE for Android offers new APIs that facilitate the development of swappable 11 | componenents that are invoked when apps request private data. This includes 12 | *Policy Managers* that can log and decide on requests to access sensitive 13 | information. Additionally, PE for Android offers the *Private Data Service* 14 | and associated modules dubbed *uPALs*, which transform private data into 15 | less sensitive forms (e.g., from full-resolution GPS coordinates to just 16 | a zip code). This modular architecture allows for the experimentation of 17 | various models for how apps use sensitive data and how users can gain 18 | insight into that. 19 | 20 | ![](architecture.png) 21 | *Apps interface with the Privacy [Abstraction] Layer (PAL). This contains 22 | the Policy Manager for regulating access to sensitive services, and uPALs 23 | to transform sensitive data prior to returning it to the requesting app.* 24 | 25 | For more details: [Full PE for Android whitepaper](PE_for_Android_whitepaper.pdf) 26 | 27 | ## How-to's 28 | 29 | * Modifying and installing PE for Android 30 | + [Building PE for Android](howto/platform/platform.md) 31 | + [Installing PE for Android](howto/phone/installation.md) 32 | 33 | * Developing apps for PE for Android 34 | + [Installing the SDK addons](howto/apps/sdk.md) 35 | + [Including the SDK addons to your project](howto/apps/sdk-project.md) 36 | + [Using PE for Android in apps](howto/apps/apps.md) 37 | + [Developing Policy Managers](howto/apps/policy.md) 38 | + [Developing uPAL modules](howto/apps/upal.md) 39 | 40 | ## Examples 41 | 42 | * [uPALs](https://github.com/twosixlabs/PE_for_Android_example_upals): 43 | various privacy-enhancing data transformations 44 | * [Signal Private Messenger](https://github.com/twosixlabs/PE_for_Android_example_signal): 45 | remove full access to contact list 46 | * [Forecastie](https://github.com/twosixlabs/PE_for_Android_example_forecastie): 47 | remove full access to location data 48 | * [Privacy Checkup](https://github.com/twosixlabs/PE_for_Android_privacycheckup): 49 | inform user of apps accessing sensitive data 50 | 51 | -------------------------------------------------------------------------------- /addon-sys-img.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 1 7 | PE for Android System Image, API 28 8 | 28 9 | x86_64 10 | pe_android 11 | PE for Android 12 | 13 | two_six_labs 14 | Two Six Labs 15 | 16 | 17 | 18 | 620625027 19 | 393f0d01947b8cdb0508e77073a4644a81cdecd3 20 | https://github.com/twosixlabs/PE_for_Android/releases/download/peandroid_v5.0.0/pea_pie_system-images_v1.zip 21 | macosx 22 | 23 | 24 | 620625027 25 | 393f0d01947b8cdb0508e77073a4644a81cdecd3 26 | https://github.com/twosixlabs/PE_for_Android/releases/download/peandroid_v5.0.0/pea_pie_system-images_v1.zip 27 | linux 28 | 29 | 30 | 620625027 31 | 393f0d01947b8cdb0508e77073a4644a81cdecd3 32 | https://github.com/twosixlabs/PE_for_Android/releases/download/peandroid_v5.0.0/pea_pie_system-images_v1.zip 33 | windows 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /addon.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | two_six_labs 7 | Two Six Labs 8 | peandroid_add-on 9 | PE for Android 10 | PE for Android Add-on 11 | 28 12 | 1 13 | 14 | com.twosixlabs.peandroid 15 | com.twosixlabs.peandroid.pal 16 | com.twosixlabs.peandroid.privacymanager 17 | 18 | 19 | 20 | 1486330 21 | d2b2b397813914a2d43529b8badd2603aa386085 22 | https://github.com/twosixlabs/PE_for_Android/releases/download/peandroid_v5.0.0/pea_pie_sdk_addon_v1.zip 23 | macosx 24 | 25 | 26 | 1486330 27 | d2b2b397813914a2d43529b8badd2603aa386085 28 | https://github.com/twosixlabs/PE_for_Android/releases/download/peandroid_v5.0.0/pea_pie_sdk_addon_v1.zip 29 | linux 30 | 31 | 32 | 1486330 33 | d2b2b397813914a2d43529b8badd2603aa386085 34 | https://github.com/twosixlabs/PE_for_Android/releases/download/peandroid_v5.0.0/pea_pie_sdk_addon_v1.zip 35 | windows 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twosixlabs/PE_for_Android/bc4dc76ca1bb7953c2273b2bc12d1d12b8ba239c/architecture.png -------------------------------------------------------------------------------- /howto/apps/apps.md: -------------------------------------------------------------------------------- 1 | # How-to: develop apps for PE for Android 2 | 3 | * [Overview](#overview) 4 | * [Example Private Data Service Call](#example-private-data-service-call) 5 | * [Specify the data source](#specify-the-data-source) 6 | - [Data type parameter helpers](#data-type-parameter-helpers) 7 | * [Specify the purpose](#specify-the-purpose) 8 | * [Specify the callback](#specify-the-callback) 9 | * [Issue the request](#issue-the-request) 10 | 11 | ## Overview 12 | 13 | Apps can take advantage of PE for Android's new Private Data Service API. This 14 | API allows apps to receive sensitive user and device data in a least-privileges 15 | manner. For example, rather than calling Android's `LocationManager`, which 16 | exposes full-fidelity location data, apps can request location data from the 17 | Private Data Service and reduce its fidelity using a uPAL (micro-PAL) module. 18 | 19 | Apps invoke the Private Data Service by by populating a `DataRequest` object 20 | and passing it to the `PrivateDataManager`. In order to avoid apps from hanging 21 | or producing ANR warnings, these requests are handled asynchronously, with the 22 | result being returned via a callback declared in the request. 23 | 24 | This guide steps through an example code snippet that calls the Private Data 25 | Service to request [zip-code-level location 26 | data](https://github.com/twosixlabs/PE_for_Android_example_upals/blob/master/app/src/main/java/com/twosixlabs/exampleupals/ZipcodeMicroPAL.java). 27 | These instructions assume that the SDK addons are [installed in your Android 28 | Studio Environment](sdk.md) and that they're [included in your 29 | project](sdk-project.md). 30 | 31 | ## Example Private Data Service call 32 | 33 | ```java 34 | // Assuming this code is in a Context-derived class (e.g., Activity, Service, etc.) 35 | Context context = this; 36 | 37 | // Specify the data source 38 | DataRequest.DataType dt = DataRequest.DataType.LOCATION; 39 | Bundle locationParams = new DataRequest.LocationParamsBuilder() 40 | .setUpdateMode(DataRequest.LocationParamsBuilder.MODE_LAST_LOCATION) 41 | .setTimeoutMillis(60000) 42 | .build(); 43 | 44 | // Specify the uPAL 45 | String pal = "com.twosixlabs.examplepals.ZipcodeMicroPAL"; 46 | Bundle palParams = null; 47 | 48 | // Specify the purpose 49 | DataRequest.Purpose purpose = DataRequest.Purpose.ADS("Paying the bills"); 50 | 51 | // Specify the callback 52 | ResultReceiver callback = new ResultReceiver(null) { 53 | @Override 54 | protected void onReceiveResult(int resultCode, Bundle resultData) { 55 | if(resultCode == PrivateDataManager.RESULT_SUCCESS) { 56 | Log.d(TAG, "Received callback"); 57 | for(String key : resultData.keySet()) { 58 | Log.d(TAG, String.format("Received data key=%s , value=%s", key, resultData.get(key).toString())); 59 | } 60 | } 61 | } 62 | }; 63 | 64 | // Issue the request 65 | DataRequest request = new DataRequest(context, 66 | dt, locationParams, 67 | pal, palParams, 68 | purpose, callback); 69 | PrivateDataManager pdm = PrivateDataManager.getInstance(); 70 | pdm.requestData(request); 71 | ``` 72 | 73 | The following sections detail discuss the key parts of making a Private Data 74 | Service Request. 75 | 76 | ## Specify the data source 77 | 78 | ```java 79 | DataRequest.DataType dt = DataRequest.DataType.LOCATION; 80 | Bundle locationParams = new DataRequest.LocationParamsBuilder() 81 | .setUpdateMode(DataRequest.LocationParamsBuilder.MODE_LAST_LOCATION) 82 | .setTimeoutMillis(60000) 83 | .build(); 84 | ``` 85 | 86 | The first step to build a Private Data Service request is to specify what 87 | sensitive data reosurce from which to retrieve information. In this example, 88 | the code specifies a request for location data. Some data types require 89 | additional parameters, detailed below. 90 | 91 | ### Data type parameter helpers 92 | 93 | The `DataRequest` class includes builder classes to construct parameters for 94 | the LOCATION, CALENDAR, and SMS data types. Other data types don't require 95 | parameters, and so the params argument can be set to anything (including 96 | `null`) in those cases. 97 | 98 | The `LocationParamsBuilder` specifies the mode of the location request (i.e., 99 | either using the last known cached location, or performing an actual location 100 | update using geolocation hardware) and how long the request can be active 101 | before it times out: 102 | 103 | ```java 104 | new DataRequest.LocationParamsBuilder() 105 | .setUpdateMode(DataRequest.LocationParamsBuilder.MODE_LAST_LOCATION) 106 | .setTimeoutMillis(60000) 107 | .build(); 108 | 109 | ``` 110 | 111 | The `MessageParamsBuilder` and `CalendarParamsBuilder` define the time window 112 | for which SMSs and calendar events, respectively, will be returned: 113 | 114 | ```java 115 | new DataRequest.MessageParamsBuilder() 116 | .setStartUtcMillis(0l) 117 | .setEndUtcMillis(1572459040000l) 118 | .build(); 119 | ``` 120 | 121 | ## Specify the uPAL 122 | 123 | ```java 124 | String pal = "com.twosixlabs.examplepals.ZipcodeMicroPAL"; 125 | Bundle palParams = null; 126 | ``` 127 | 128 | A Private Data Service request must specify the uPAL that will transform the 129 | sensitive data before returning it to the calling app. The uPAL developer 130 | is responsible for documenting the uPAL identifier, parameters (if any), and 131 | accepted data types. 132 | 133 | Note that that uPALs can be installed separately from the calling app. Calling 134 | an unavailable uPAL will result in a `null` data bundle passed back to the 135 | requesting app. 136 | 137 | ## Specify the purpose 138 | 139 | ```java 140 | DataRequest.Purpose purpose = DataRequest.Purpose.ADS("Paying the bills"); 141 | ``` 142 | 143 | PE for Android requires Private Data Service requests to specify the purpose 144 | for the data access. [Policy managers](policy.md) can operate on declared 145 | purposes in granting or denying access to sensitive resources. 146 | 147 | The `DataRequest.Purpose` inner class defines available purposes. To 148 | declare a purpose, select the desired purpose and provide a human-readable 149 | explanation for the request. 150 | 151 | ```java 152 | DataRequest.Purpose.ADS("Paying the bills"); 153 | DataRequest.Purpose.SOCIAL("Integration with Facebook"); 154 | ``` 155 | 156 | ## Specify the callback 157 | 158 | ```java 159 | ResultReceiver callback = new ResultReceiver(null) { 160 | @Override 161 | protected void onReceiveResult(int resultCode, Bundle resultData) { 162 | if(resultCode == PrivateDataManager.RESULT_SUCCESS) { 163 | Log.d(TAG, "Received callback"); 164 | for(String key : resultData.keySet()) { 165 | Log.d(TAG, String.format("Received data key=%s , value=%s", key, resultData.get(key).toString())); 166 | } 167 | } 168 | } 169 | }; 170 | ``` 171 | 172 | After the uPAL finishes transforming the requested data, it returns its result 173 | via callback. Callbacks should check the result code before processing the 174 | incoming data. In this example, the callback simply prints out all the 175 | key-value pairs inside the incoming data bundle sent by the uPAL. 176 | 177 | ## Issue the request 178 | 179 | ```java 180 | DataRequest request = new DataRequest(context, 181 | dt, locationParams, 182 | pal, palParams, 183 | purpose, callback); 184 | PrivateDataManager pdm = PrivateDataManager.getInstance(); 185 | pdm.requestData(request); 186 | ``` 187 | 188 | The `PrivateDataManager` is the entry-point for the Private Data Service. Use 189 | an instance of the `PrivateDataManager` to issue the request for uPAL-transformed 190 | data. The callback specified in the request will run asynchronously upon the 191 | completion of the request. 192 | 193 | -------------------------------------------------------------------------------- /howto/apps/instant-run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twosixlabs/PE_for_Android/bc4dc76ca1bb7953c2273b2bc12d1d12b8ba239c/howto/apps/instant-run.png -------------------------------------------------------------------------------- /howto/apps/policy-settings-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twosixlabs/PE_for_Android/bc4dc76ca1bb7953c2273b2bc12d1d12b8ba239c/howto/apps/policy-settings-1.png -------------------------------------------------------------------------------- /howto/apps/policy-settings-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twosixlabs/PE_for_Android/bc4dc76ca1bb7953c2273b2bc12d1d12b8ba239c/howto/apps/policy-settings-2.png -------------------------------------------------------------------------------- /howto/apps/policy.md: -------------------------------------------------------------------------------- 1 | # How-to: develop policy managers 2 | 3 | * [Overview](#overview) 4 | * [Example Policy Manager](#example-policy-manager) 5 | * [Permission hooks](#permission-hooks) 6 | * [Registering the service](#registering-the-service) 7 | * [Deploying a Policy Manager](#deploying-a-policy-manager) 8 | 9 | ## Overview 10 | 11 | Policy Managers are trusted apps that have the ability to grant or deny access 12 | to sensitive resources. PE for Android invokes the current active Policy 13 | Manager when apps are installed, as well as when apps request 14 | [dangerous permissions](https://developer.android.com/guide/topics/permissions/overview) 15 | or use the [Private Data Service](apps.md). 16 | 17 | Given this component's privileged position in PE for Android's permission 18 | system, Developers can implement novel permission controls and transparency 19 | tools as Policy Managers. And developers can do so using standard Android app 20 | development and deployment processes, without needing to modify the platform 21 | code itself. 22 | 23 | This guide serves as an introduction to the main concepts of Policy Manager 24 | development. The following assumes that the PE for Android SDK addons 25 | are already [installed in Android Studio](sdk.md) and that the addons 26 | have been [included in the project](sdk-project.md). Additionally, as 27 | Policy Managers are trusted components, PE for Android requires that 28 | Policy Manager apps are [properly signed](sdk-project.md#signing-policy-managers-and-upals). 29 | 30 | ## Example Policy Manager 31 | 32 | ```java 33 | public class DummyPolicyManagerService extends PolicyManagerService { 34 | @Override 35 | public boolean onAppInstall(String packageName, String odp) { 36 | return true; 37 | } 38 | 39 | @Override 40 | public void onDangerousPermissionRequest(String packageName, String permission, 41 | String purpose, 42 | List stackTrace, 43 | int flags, 44 | ComponentName callingComponent, 45 | ComponentName topActivity, 46 | ResultReceiver recv) { 47 | Bundle bundle = new Bundle(); 48 | bundle.putBoolean("allowPerm", true); 49 | recv.send(0, bundle); 50 | } 51 | 52 | @Override 53 | public void onPrivateDataRequest(String packageName, String permission, 54 | String purpose, String pal, 55 | String description, ResultReceiver recv) { 56 | Bundle bundle = new Bundle(); 57 | bundle.putBoolean("allowPerm", true); 58 | recv.send(0, bundle); 59 | } 60 | } 61 | ``` 62 | 63 | ## Permission hooks 64 | 65 | The `PolicyManagerService` base class exposes three abstract methods that a 66 | Policy Manager implementation must define: 67 | 68 | * `boolean onAppInstall()`: Called when an app is installed 69 | * `void onDangerousPermissionRequest()`: Called when a dangerous permission is requested via the stock Android API 70 | * `void onPrivateDataRequest()`: Called when an app makes a request to the [Private Data Service](apps.md) 71 | 72 | All three of these hooks return a true/false result indicating if the corresponding 73 | action was granted. `onDangerousPermissionRequest()` and `onPrivateDataRequest()` do 74 | this via a callback, as those permission checks are done asynchronously. 75 | 76 | ## Registering the service 77 | 78 | ```xml 79 | 84 | 85 | 86 | 87 | 88 | ``` 89 | 90 | The Policy Manager's core service must declare the `POLICY_MANAGER_SERVICE` 91 | permission in order to use hooks exposed by the PE for Android API. 92 | Additionally, the service needs to listen for broadcasts of the 93 | `android.app.action.DEVICE_POLICY_MANAGER_START` in order to be set 94 | as the active Policy Manager. 95 | 96 | ## Deploying a Policy Manager 97 | 98 | As Policy Managers are regular Android apps (albeit with additional permissions 99 | and a specific signing key), developers and users can install them as they 100 | would any other app: via Android Studio, or with the `adb install` command. 101 | 102 | Multiple Policy Managers can be present on a device simultaneously. However, 103 | only one can be set as the active one. The user can set the active Policy 104 | Manager by opening the device's system Settings and using the PE for Android 105 | Settings panel. 106 | 107 | ![](policy-settings-1.png) ![](policy-settings-2.png) 108 | 109 | -------------------------------------------------------------------------------- /howto/apps/sdk-add-site.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twosixlabs/PE_for_Android/bc4dc76ca1bb7953c2273b2bc12d1d12b8ba239c/howto/apps/sdk-add-site.png -------------------------------------------------------------------------------- /howto/apps/sdk-installed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twosixlabs/PE_for_Android/bc4dc76ca1bb7953c2273b2bc12d1d12b8ba239c/howto/apps/sdk-installed.png -------------------------------------------------------------------------------- /howto/apps/sdk-path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twosixlabs/PE_for_Android/bc4dc76ca1bb7953c2273b2bc12d1d12b8ba239c/howto/apps/sdk-path.png -------------------------------------------------------------------------------- /howto/apps/sdk-project.md: -------------------------------------------------------------------------------- 1 | # How-to: including the SDK addons to your project 2 | 3 | * [Overview](#overview) 4 | * [build.gradle changes](#buildgradle-changes) 5 | - [Signing Policy Managers and uPALs](#signing-policy-managers-and-upals) 6 | - [local.properties workaround](#localproperties-workaround) 7 | * [AndroidManifest.xml changes](#androidmanifestxml-changes) 8 | * [Enabling inline Javadocs](#enabling-inline-javadocs) 9 | 10 | ## Overview 11 | 12 | The PE for Android SDK addons enable apps to use PE for Android's new 13 | APIs. Apps that implement Policy Managers, uPALs, or use the Private Data 14 | Service must integrate with the SDK addons. 15 | 16 | After [installing the addons](sdk.md), the following steps will allow an Android Studio 17 | project to take advantage of PE for Android's features. 18 | 19 | ## build.gradle changes 20 | 21 | The app-level `build.gradle` file specifies the target platform for the 22 | project. Apps that use PE for Android's features must specify this 23 | accordingly: 24 | 25 | ``` 26 | android { 27 | ... 28 | 29 | compileSdkVersion 'Two Six Labs:PE for Android:28' 30 | 31 | ... 32 | 33 | defaultConfig { 34 | ... 35 | minSdkVersion 28 36 | targetSdkVersion 28 37 | ... 38 | } 39 | 40 | ... 41 | } 42 | ``` 43 | 44 | ### Signing Policy Managers and uPALs 45 | 46 | PE for Android considers Policy Managers and uPAL modules as trusted software. 47 | Implementations of these must be signed by the system key, else PE for Android 48 | will block their installation. The following will tell Android Studio to 49 | generate a properly signed APK when compiling the project: 50 | 51 | 1. Obtain the [PE for Android signing key](https://github.com/twosixlabs/PE_for_Android/raw/master/PE_for_Android.keystore) and save it in the same directory as the app-level `build.gradle` 52 | 53 | 2. Add the following lines to the app-level `build.gradle`: 54 | 55 | ``` 56 | android { 57 | ... 58 | 59 | signingConfigs { 60 | PAL_config { 61 | keyAlias 'peandroid' 62 | keyPassword 'peandroid' 63 | storeFile file('PE_for_Android.keystore') 64 | storePassword 'peandroid' 65 | } 66 | } 67 | 68 | ... 69 | 70 | buildTypes { 71 | release { 72 | ... 73 | signingConfig signingConfigs.PAL_config 74 | ... 75 | } 76 | 77 | debug{ 78 | ... 79 | signingConfig signingConfigs.PAL_config 80 | ... 81 | } 82 | } 83 | 84 | ... 85 | ``` 86 | 87 | ### local.properties workaround 88 | 89 | There's an unresolved bug that prevents newer versions of Gradle from properly 90 | finding and including the SDK addons library. Explicitly declaring the path to 91 | your Android SDK directory serves as a workaround for this bug. 92 | 93 | You can find your Android SDK directory using Android Studio: 94 | 95 | 1. Open any Android Studio project 96 | 2. Open the "Tools" menu and select "SDK Manager" 97 | 3. The Android SDK location will be shown near the top of the window 98 | 99 | ![](sdk-path.png) 100 | 101 | After obtaining this information, create a `local.properties` file in your Android 102 | Studio project's top-level directory (if it doesn't already exist). Include the 103 | following line to declare the path to your Android SDK. Change accordingly to 104 | where the SDK is installed on your system. 105 | 106 | ``` 107 | sdk.dir=/home/user/Android/Sdk 108 | ``` 109 | 110 | ## AndroidManifest.xml changes 111 | 112 | You will need to include the appropriate PE for Android library within your app's manifest. The library you include will vary 113 | depending on if you are creating a PE for Android App, a Policy Manager, or a uPAL 114 | 115 | | Project Type | Library | 116 | |--------------------|-------------------------------------------| 117 | | PE for Android App | `com.twosixlabs.peandroid` | 118 | | Policy Manager | `com.twosixlabs.peandroid.privacymanager` | 119 | | uPAL | `com.twosixlabs.peandroid.pal` | 120 | 121 | The necessary library can be included by adding a `uses-library` line to the `` tag of your apps manifest. 122 | 123 | ```xml 124 | 125 | ``` 126 | 127 | ## Enabling inline Javadocs and code autocomplete 128 | 129 | The PE for Android SDK addons come with Javadocs-style inline documentation. The 130 | following steps will enable Android Studio to show this documentation in the 131 | editor: 132 | 133 | 1. In the 'Project' pane on the left of Android Studio, switch the view to 134 | **'Project'** 135 | 2. Expand **Exeternal Libraries** and right click on the library you would 136 | like to add JavaDocs for 137 | 1. This will correspond to the library you specified in your 138 | AndroidManifest.xml (i.e. **privacymanager-android-28**) 139 | 3. Click on **'Library Properties'** 140 | 4. Click the **'+'** button to open a file browser dialog 141 | 1. It should open to the **'libs'** directory of the SDK Addon 142 | 5. Expand the **'docs'** directory and select the documentation 143 | directory for the library you are using. 144 | 6. Android Studio should detect these as JavaDocs, and you can select "OK" 145 | 146 | After completing this process you should now be able to launch **'Quick 147 | Documentation'** or **'External Documentation'** through Android Studio's 148 | shortcuts or by clicking on **View->Quick Documentation** 149 | 150 | To enable proper autocomplete features in Android Studio, you will also need 151 | to add the peandroid stubbed source files. Enabling this is essentially the 152 | same as enabling JavaDocs. 153 | 154 | 1. Like before, open **'Library Properties'** for the specified library. 155 | 2. Click the **'+'** button to open a file browser dialog 156 | 3. Expand the **'src'** dialog, and select the proper .jar file for your 157 | library (i.e. **privacymanager.jar**) 158 | 4. Android Studio should detect these as Sources, and you can select "OK" 159 | 160 | The latest version of standalone Javadocs may be found on the PE for Android webpage [here](https://android-privacy.org/#documentation) -------------------------------------------------------------------------------- /howto/apps/sdk.md: -------------------------------------------------------------------------------- 1 | # How-to: install the SDK addons 2 | 3 | ## Overview 4 | 5 | These instructions show how to install the SDK addons in Android Studio. 6 | Specific usage instructions are detailed in the individual how-to's for 7 | developing [apps that use the Private Data Service](apps.md), [Policy 8 | Managers](policy.md), and [uPAL modules](upal.md). 9 | 10 | ## Installing the SDK addons 11 | 12 | We offer precompiled SDK addons that can be installed using Android Studio's 13 | built-in SDK manager. 14 | 15 | 1. Open any Android Studio project. 16 | 2. Open the "Tools" menu and select the "SDK Manager" tab 17 | 3. Click the "SDK Update Sites" tab 18 | 4. On the right side of the window, click the `+` button to add a site 19 | 5. Enter the following details: 20 | 21 | ``` 22 | Name: PE for Android SDK Addons 23 | URL: https://raw.githubusercontent.com/twosixlabs/PE_for_Android/master/addon.xml 24 | ``` 25 | 26 | ![](sdk-add-site.png) 27 | 28 | 6. After adding the site, enable it by checking the box 29 | 7. Click "OK" in the SDK Manager to accept this new site 30 | 8. Open the SDK manager again and wait for the "SDK Platforms" tab to populate 31 | 9. Check the box for "Show Package Details" 32 | 10. Expand the options under "Android 9.0 (Pie)" and ensure that PE for 33 | Android, Android SDK Platform 28, and Sources for Android 28 are enabled as shown: 34 | 35 | ![](sdk-installed.png) 36 | 37 | 11. Click "OK" in the SDK Manager to accept these SDK options 38 | 39 | ### Custom SDK addons 40 | 41 | If you compiled your own version of PE for Android, you can generate 42 | corresponding SDK addons that capture any API changes you may have implemented. 43 | See the [build instructions](../platform/platform.md) for details about 44 | packaging your own SDK addons. To install custom versions of the SDK addons in 45 | Android Studio, simply change the URL in step 5 above to point to local file 46 | path of the generated `addon.xml`. 47 | 48 | -------------------------------------------------------------------------------- /howto/apps/upal.md: -------------------------------------------------------------------------------- 1 | # How-to: develop uPAL modules 2 | 3 | * [Overview](#overview) 4 | * [Example uPAL](#example-upal) 5 | * [Extending the base class](#extending-the-base-class) 6 | + [Declaring the constructor](#declaring-the-constructor) 7 | + [Implementing the abstract methods](#implementing-the-abstract-methods) 8 | * [Registering the uPAL](#registering-the-upal) 9 | * [Recommended practices](#recommended-practices) 10 | 11 | ## Overview 12 | 13 | PE for Android allows apps to access sensitive data via the [Private Data 14 | Service](apps.md), in lieu of standard Android APIs like `LocationManager` and 15 | `ContactsContract`. Full-resolution data (e.g., GPS coordinates, whole contact 16 | lists) stays entirely within the Private Data Service, which uses uPAL modules 17 | ("micro-Privacy Abstraction Layer modules") to reduce the resolution of that 18 | information down to just what the app needs. 19 | 20 | Developers can implement their own uPAL modules and distribute them as 21 | modular transformations, reusable in any app that interfaces with the Private 22 | Data Service. 23 | 24 | As an example demonstrating the development of uPALs, this guide steps through a uPAL 25 | that receives contact list data from the system and a known phone number from the 26 | calling app. The uPAL then returns the name associated with that phone number, if 27 | available from the contact list. The requesting app only receives this result, 28 | without gaining access to the entire contact list. 29 | 30 | ## Example uPAL 31 | 32 | ```java 33 | public class NumberToNamePAL extends MicroPALProviderService> { 34 | private static final String TAG = NumberToNamePAL.class.getSimpleName(); 35 | private static final String DESCRIPTION = "Get the matching name from the contact list given a known phone number"; 36 | 37 | public static final String PHONE_KEY = "phone"; 38 | public static final String NAME_KEY = "name"; 39 | 40 | public NumberToNamePAL() { 41 | super(DataRequest.DataType.CONTACTS); 42 | } 43 | 44 | @Override 45 | public Bundle onReceive(ListItem contactItemList, Bundle paramsFromApp) { 46 | if(paramsFromApp.containsKey(PHONE_KEY)) { 47 | String inputPhoneNumber = normalizePhoneNumber(paramsFromApp.getString(PHONE_KEY)); 48 | Log.i(TAG, "Checking for phone number " + inputPhoneNumber); 49 | 50 | for(ContactItem contact : contactItemList.getStoredItems()) { 51 | // Contacts could have more than one phone number 52 | ArrayList phoneNumbers = contact.getPhoneNumbers(); 53 | for(String phoneNumber : phoneNumbers) { 54 | String contactPhoneNumber = normalizePhoneNumber(phoneNumber); 55 | 56 | if(inputPhoneNumber.equals(contactPhoneNumber)) { 57 | String name = contact.getName(); 58 | Log.i(TAG, "Found name " + name + " corresponding to phone number " + inputPhoneNumber); 59 | 60 | Bundle result = new Bundle(); 61 | result.putString(PHONE_KEY, inputPhoneNumber); 62 | result.putString(NAME_KEY, name); 63 | 64 | return result; 65 | } 66 | } 67 | } 68 | 69 | Log.w(TAG, "No contact name found for " + inputPhoneNumber); 70 | 71 | } else { 72 | Log.e(TAG, String.format("Need to provide an input bundle with key '%s' corresponding to the phone number", PHONE_KEY)); 73 | } 74 | 75 | return null; 76 | } 77 | 78 | @Override 79 | public String getDescription() { 80 | return DESCRIPTION; 81 | } 82 | 83 | /** 84 | * 85 | * @param phoneNumber 86 | * @return The phone number only containing numerics; all other symbols are stripped out 87 | */ 88 | private String normalizePhoneNumber(String phoneNumber) { 89 | return phoneNumber.replaceAll("\\D+", ""); 90 | } 91 | } 92 | ``` 93 | 94 | ## Extending the base class 95 | 96 | All uPALs must extend the `MicroPALProviderService` base class and declare the 97 | type of system API data they expect to receive. 98 | 99 | ```java 100 | public class NumberToNamePAL extends MicroPALProviderService> { 101 | // ... 102 | } 103 | 104 | ``` 105 | 106 | The parameterized type must be an `Item` or any class derived from it. The following 107 | `Item` types are available: 108 | 109 | | Item type | DataRequest.DataType type | Notes 110 | | ------------------------------------- | --------------------------------- | --------------------------------------------------------------------- | 111 | | Item | ANY | uPAL will operate on any Item-derived data type | 112 | | EmptyItem | EMPTY | uPAL will ignore the Item and only operate on the PAL params Bundle | 113 | | ListItem\ | CALL\_LOGS | List of incoming and outgoing calls | 114 | | ListItem\ | CONTACTS | Full contact list | 115 | | ListItem\ | CALENDAR | List of calendar events within a given time | 116 | | ListItem\ | SMS | List of incoming and outgoing SMS within given time. See note below | 117 | | LocationItem | LOCATION | Latitude/longitude data | 118 | | DeviceStateItem | PHONE\_STATE | Information about the phone | 119 | 120 | **Note**: The current implementation only operates on text-only messages 121 | between individual contacts. Group SMS and MMS are unsupported. 122 | 123 | ### Declaring the constructor 124 | 125 | The uPAL's constructor must declare the matching `DataRequest.DataType` and 126 | pass it up to the superclass. 127 | 128 | ```java 129 | public NumberToNamePAL() { 130 | super(DataRequest.DataType.CONTACTS); 131 | } 132 | ``` 133 | 134 | ### Implementing the abstract methods 135 | 136 | uPALs must implement two abstract methods from the superclass: `onReceive()` and 137 | `getDescription`. 138 | 139 | #### onReceive() 140 | 141 | ```java 142 | public Bundle onReceive(ListItem contactItemList, Bundle paramsFromApp) { 143 | // ... 144 | } 145 | ``` 146 | 147 | This method transforms sensitive data as received from system API calls (i.e., 148 | the `Item`-typed first parameter) and given by the app (i.e., the `Bundle`-typed 149 | second parameter). You may choose to ignore either one or both of these parameters 150 | in your uPAL transformation. 151 | 152 | The result of this method is sent back to the calling app. Returning `null` will 153 | indicate to the calling app that a failure occurred. 154 | 155 | #### getDescription() 156 | 157 | ```java 158 | public String getDescription() { 159 | return DESCRIPTION; 160 | } 161 | ``` 162 | 163 | This method defines a human-readable description of the uPAL. 164 | 165 | ## Registering the uPAL 166 | 167 | uPALs must declare their ability to listen for data transformation requests from 168 | the Private Data Service. Ensure that the uPAL's core service has has the 169 | `android.permission.PRIVATE_DATA_PROVIDER_SERVICE` permission and the 170 | `android.privatedata.MicroPALProviderService` intent filter in the app's 171 | manifest. 172 | 173 | ```xml 174 | 178 | 179 | 180 | 181 | 182 | ``` 183 | 184 | ## Recommended practices 185 | 186 | Although uPALs are executed asynchronously, they're meant to be lightweight 187 | functions that [do one thing and do it well](https://en.wikipedia.org/wiki/Unix_philosophy). 188 | uPAL developers should try to abide by the following practices to ensure 189 | their transformations follow this design goal. 190 | 191 | * uPALs should be stateless. Any state should be maintained by the calling app 192 | and passed back to the uPAL using the params `Bundle` in subsequent calls. 193 | * uPALs should avoid I/O operations such as disk and network functions. I/O 194 | is relatively slow and can be unreliable, leading to uPALs that potentially 195 | don't terminate. 196 | * A single APK can hold many distinct independent uPALs. Split up disparate 197 | loosely-related transformations into individual uPAL services. 198 | 199 | 200 | -------------------------------------------------------------------------------- /howto/phone/installation.md: -------------------------------------------------------------------------------- 1 | # How-to: Install PE for Android on a phone 2 | 3 | * [Overview](#overview) 4 | * [Initial device preparation](#initial-device-preparation) 5 | + [Unlocking the bootloader](#unlocking-the-bootloader) 6 | + [Flashing the correct base Android version](#flashing-the-correct-base-android-version) 7 | * [Flashing PE for Android](#flashing-pe-for-android) 8 | * [Google Play installation](#google-play-installation) 9 | + [Installing Open GApps](#installing-open-gapps) 10 | + [Register custom ROM with Google Play Services](#register-custom-rom-with-google-play-services) 11 | 12 | ## Overview 13 | 14 | PE for Android was forked from AOSP's [Generic System Images 15 | (GSI)](https://developer.android.com/topic/generic-system-image) for Android Pie and should be 16 | compatible with any [Project Treble-compliant 17 | device](https://play.google.com/store/apps/details?id=com.kevintresuelo.treble&hl=en_US) that meet 18 | [these requirements](https://source.android.com/setup/build/gsi#flashing-gsis). Through our 19 | development we have tested PE for Android with the Pixel 2XL and Pixel 3aXL, although other 20 | Pixel devices should behave similarly to those. Below is a table of Google Pixel devices 21 | and the corresponding images that should be compatible with the phone. The images for the various 22 | types of GSI builds are available [here](https://github.com/twosixlabs/PE_for_Android/releases). 23 | 24 | 25 | | Device | Codename | GSI Image Type | 26 | |--------|----------|----------------| 27 | | Pixel 2 | walleye | gsi_ab | 28 | | Pixel 2XL | taimen | gsi_ab | 29 | | Pixel 3 | blueline | gsi| 30 | |Pixel 3XL | crosshatch | gsi | 31 | |Pixel 3a | sargo | gsi | 32 | |Pixel 3aXL | bonito | gsi | 33 | 34 | 35 | While we have only tested on Pixel devices, installing PE for Android on other GSI-compatible 36 | devices will take similar steps to these specified here. Please refer to the [official GSI 37 | documentation](https://source.android.com/setup/build/gsi) for more information on GSI's 38 | in general. Additionally, the [XDA Developer forums](https://forum.xda-developers.com/) 39 | contain a wealth of information that may be useful in flashing the PE for Android GSI 40 | to your phone. 41 | 42 | 43 | These instructions assume familiarity with the command line and that the 44 | Android command-line tools (e.g., _adb_ and _fastboot_) are already installed 45 | on your system. These tools are part of Android Studio but may also be 46 | installed separately. This software is available for download on the [Android 47 | Studio downloads page](https://developer.android.com/studio/#downloads). 48 | 49 | ## Initial device preparation 50 | 51 | These steps are only necessary for bootloader-locked devices running stock 52 | Android. If your device's bootloader is already unlocked, you may skip that 53 | process. Likewise, if your bootloader-unlocked device is already running an 54 | appropriate version of Android, you may skip this section altogether. 55 | 56 | ### Unlocking the bootloader 57 | 58 | Unlocking the bootloader allows users to manipulate the device's partitions and 59 | install new system images, including PE for Android GSI images. While each device 60 | may have different steps below is a link to the process to unlock Google Devices. 61 | Again, if you do not have a Google device it is best to refer to the 62 | [XDA Developer forums](https://forum.xda-developers.com/) to see if and how your 63 | device bootloader may be unlocked. 64 | 65 | **WARNING**: The process of unlocking the bootloader will factory-reset your 66 | device. Please ensure you have a backup of your data before proceeding. 67 | 68 | * [Unlocking the Bootloader on Google Devices](https://source.android.com/setup/build/running#unlocking-the-bootloader) 69 | 70 | **NOTE**: Unlocking the bootloader will cause the device to display a boot 71 | warning that reads "The bootloader is unlocked and software integrity 72 | cannot be guaranteed." You may ignore this message. 73 | 74 | ### Flashing the correct base Android version 75 | 76 | For flashing GSIs we have discovered some nuances to both installing on the Pixel 3aXL, 77 | as well as the 2XL. 78 | 79 | We have found the for the Pixel 3aXL, you must start from a stock 80 | Android 9 base image to ensure the appropriate vendor binaries are on the device 81 | to allow the various hw components to work. We have not found a method for installing the 82 | the PE for Android GSI over a stock Android 10 Pixel 3aXL. 83 | 84 | For the Pixel 2XL, we have discovered only a specific version of stock firmware that 85 | allows for a clean boot. If flashing for the Pixel 2XL, please first flash the 86 | [PQ3A.190605.003, Jun 2019](https://dl.google.com/dl/android/aosp/taimen-pq3a.190605.003-factory-59303ad9.zip) 87 | build. 88 | 89 | For flashing instructions and stock images for Pixel devices, please refer to Google's 90 | website. 91 | 92 | [Pixel Factory Images](https://developers.google.com/android/images) 93 | 94 | 95 | ## Flashing PE for Android 96 | 97 | After following the above instructions to [prepare a new 98 | device](#initial-device-preparation), the device will be ready to install PE 99 | for Android. 100 | 101 | 1. Download *vbmeta.img* and *system.img* for the appropriate PE for Android 102 | release available 103 | [here](https://github.com/twosixlabs/PE_for_Android/releases). Alternatively, 104 | these files may be generated by [building PE for Android from 105 | source](https://github.com/twosixlabs/PE_for_Android/blob/master/howto/platform/platform.md). 106 | 2. Connect the device to your computer via USB 107 | 2. Boot into the bootloader with `adb reboot bootloader` 108 | 3. Run the following commands to install the downloaded *.img* files: 109 | 110 | ``` 111 | $ fastboot --disable-verification flash vbmeta vbmeta.img 112 | $ fastboot erase system 113 | $ fastboot flash system system.img 114 | $ fastboot -w 115 | $ fastboot reboot 116 | ``` 117 | 118 | ## Google Play Installation 119 | 120 | PE for Android does not come with proprietary Google apps (e.g., Google Maps, 121 | Play Store, Gmail, etc.) commonly found on most Android phones. These must 122 | be installed separately after flashing PE for Android. This is commonly achieved 123 | through a custom device recovery and appropriate download from OpenGapps 124 | 125 | ### Installing Open Gapps 126 | 127 | To install OpenGapps, the TWRP custom recovery is commonly used and generally 128 | widely supported for various devices. The TWRP custom recovery allows the user 129 | to install packages (such as Google apps) to the normally write-protected system 130 | partition. The following instructions show how to boot to TWRP and install OpenGapps. 131 | 132 | PE for Android increased the system partition size to more easily allow for 133 | the installation of OpenGapps. However, this increase is only suitable for installing 134 | the *pico* variant for Android 9.0 on ARM64 found [here](https://opengapps.org/). 135 | 136 | **Note:** If the device already has TWRP, you may skip to step ***#5*** in instructions and 137 | continue installing the Open GApps package. 138 | 139 | 1. Download the latest version of TWRP for your device from 140 | [TWRP's webpage](https://twrp.me/Devices/). You will only need the *img* file, unless you want to permanently install TWRP. 141 | 2. Download Open GApps (*pico* variant) for Android 9.0 on ARM64 [here](https://opengapps.org/) 142 | 3. Enter fastboot mode on your phone either by key combination or `adb reboot bootloader` if your phone is powered on 143 | 4. Temporarily boot into TWRP with `fastboot boot twrp--a.b.c-d.img` 144 | 5. When TWRP boots up, run `*adb push open_gapps-arm64-9.0-pico-yyyymmdd.zip /sdcard/*` 145 | 6. Select "Install" and navigate to /sdcard and select '*open_gapps-arm64-9.0-pico-yyyymmdd.zip*' 146 | 7. Activate the slider to install Open GApps 147 | 9. When finished, reboot the device back to the home screen 148 | 149 | **NOTE**: If the screen is unresponsive in step 5, try issuing the following 150 | commands from the shell: 151 | 152 | ```shell 153 | $ adb shell 154 | $ twrp install /sdcard/open_gapps-arm64-9.0-pico-yyyymmdd.zip 155 | $ reboot 156 | ``` 157 | 158 | If you re-flash *system.img* on the device (i.e., update to a newer 159 | version of PE for Android), you will need to follow the [Installing Open GApps](#installing-open-gapps) 160 | steps again. Failing to re-install Open GApps will result in Google Play 161 | Services constantly crashing. 162 | 163 | ### Register custom ROM with Google Play Services 164 | 165 | The phone will have a constant stream of notifications saying the device is not 166 | compliant with Google policies. Tapping on the notification will take you to a 167 | URL that's hard to read on the phone. Go 168 | [here](https://g.co/AndroidDeviceRegistration) to register the phone. 169 | 170 | The commands on the page generate a long number to paste into the page and 171 | click Register. Once you've done that, reboot the phone. 172 | 173 | Within a couple of minutes, the Play Protect messages should stop and you will 174 | see ones related to updating Play Services and app update availability in the 175 | Play Store. 176 | 177 | -------------------------------------------------------------------------------- /howto/platform/platform.md: -------------------------------------------------------------------------------- 1 | # How-to: build the PE for Android platform 2 | 3 | * [Overview](#overview) 4 | * [Initializing the source tree](#initializing-the-source-tree) 5 | * [Docker environment initialization](#docker-environment-initialization) 6 | * [Using Docker to build PE for Android](#using-docker-to-build-pe-for-android) 7 | 8 | ## Overview 9 | 10 | PE for Android is an open-source fork of the Android Open Source Project 11 | release for Android 9 (Pie). While the its Policy Manager and uPAL paradigms 12 | offer much flexibility in implementing privacy-enhancing concepts as user-space 13 | apps, we understand that there could be use cases where the platform still 14 | needs to be modified. We invite other developers and researchers to extend PE 15 | for Android for their own needs. This is a guide for how to clone and build 16 | PE for Android from source. 17 | 18 | These instructions assume familiarity with the Linux shell, the AOSP code 19 | structure, and that Docker and [Google's `repo` 20 | tool](https://source.android.com/setup/build/downloading#installing-repo) are 21 | already installed on the system. For minimal complications, we recommend 22 | building PE for Android on a 64-bit Linux system with at least 750 GBs of free 23 | disk space. Additional CPU cores, memory, and solid-state storage will speed up 24 | the compilation process. 25 | 26 | ## Initializing the source tree 27 | 28 | The AOSP source tree is organized as a collection of [several hundred Git 29 | repositories](https://android-review.googlesource.com/admin/repos), each 30 | corresponding to a particular directory in the tree. Developers use the `repo` 31 | tool to manage these Git repositories and perform batch operations on them. 32 | Different AOSP builds exist for each target device. To simplify management of 33 | all the component Git repositories, each target device has a `manifest.xml` 34 | file that defines particular repositories and branches needed to build AOSP for 35 | that target. 36 | 37 | For PE for Android, we use the Generic System Image (GSI) target for Android 9 38 | ("Pie"). The following commands will initialize the metadata for this target. 39 | 40 | ```shell 41 | > mkdir $PE_ANDROID_ROOT 42 | > cd $PE_ANDROID_ROOT 43 | > repo init -u https://android.googlesource.com/platform/manifest -b pie-gsi 44 | ``` 45 | 46 | After initializing the for metadata for Android 9, we include the 47 | `local_manifests` metadata that points to the code specific to PE for Android. 48 | 49 | ```shell 50 | > cd .repo 51 | > git clone https://github.com/twosixlabs/pea_local_manifests.git local_manifests 52 | > cd .. 53 | ``` 54 | 55 | With all the metadata in place, we can download the specified source files. Note that 56 | this step may take many minutes or hours, depending on your Internet connection. 57 | 58 | ```shell 59 | > repo sync -c -j8 60 | ``` 61 | **FOR TEAMS**: These commands will download the AOSP source from Google's 62 | servers. These servers have rate-limiting restrictions. If multiple team members 63 | are cloning the source tree simultaneously, the rate-limiting will likely 64 | trigger and cause errors in the cloning process. In order to mitigate this, 65 | teams may wish to [set up a local mirror](https://source.android.com/setup/build/downloading#using-a-local-mirror) 66 | so files are cloned from Google's servers only once. Developers subsequently 67 | clone from the local mirror, and thus are not subject to rate-limiting. If 68 | cloning from a local mirror, ensure that the `repo init` command above is 69 | pointing to the mirror's manifest. 70 | 71 | ## Docker environment initialization 72 | 73 | For convenience, we offer a Docker container preconfigured with all the 74 | dependencies settings needed to build PE for Android. The following commands 75 | will initialize the Docker container and launch it. These commands should 76 | be done in a path *outside* the `$PE_ANDROID_ROOT` directory used in the 77 | previous section. 78 | 79 | ```shell 80 | > mkdir $PE_ANDROID_DOCKER 81 | > cd $PE_ANDROID_DOCKER 82 | > curl https://raw.githubusercontent.com/twosixlabs/PE_for_Android_dockerfile/master/Dockerfile > Dockerfile 83 | > sudo docker build --no-cache -t peandroid:pie ./ 84 | ``` 85 | 86 | ## Using Docker to build PE for Android 87 | 88 | After Docker builds the image for the environment, the following commands will 89 | start an interactive session in a new Docker container. Let `$PE_ANDROID_ROOT` 90 | be the path to your PE for Android source tree, defined earlier. 91 | 92 | ```shell 93 | > cd $PE_ANDROID_DOCKER 94 | > sudo docker run -v $PE_ANDROID_ROOT:/src/ -w /src -it --rm peandroid:pie 95 | ``` 96 | This maps `$PE_ANDROID_ROOT` to the Docker container's `/src` directory 97 | and launches the container. From `/src` there are three shell scripts 98 | to build different variants of PE for Android: 99 | 100 | * `make_gsi.sh`: Builds a GSI 101 | * `make_gsi_a.sh`: Builds a GSI for legacy A-partition devices 102 | * `make_gsi_ab.sh`: Builds a GSI for legacy AB-partition devices 103 | * `make_peandroid.sh`: Builds the SDK addons and emulator image 104 | 105 | These scripts save their terminal outputs to `build_gsi.log`, `build_gsi_a.log`, 106 | `build_gsi_ab.log`, and `addons.log`. 107 | 108 | System image files are saved under 109 | `$PE_ANDROID_ROOT/out/target/product/generic_arm64`, `$PE_ANDROID_ROOT/out/target/product/generic_arm64_a`, and `$PE_ANDROID_ROOT/out/target/product/generic_arm64_ab` for `make_gsi.sh`, `make_gsi_a.sh`, and`make_gsi_ab.sh`, respectively. 110 | 111 | `make_peandroid.sh` saves the SDK addons under 112 | `$PE_ANDROID_ROOT/out/host/linux-x86/sdk_addon/`. Despite the path name, SDK 113 | addons are platform-agnostic and should work with Linux, Windows, and Mac 114 | versions of Android Studio alike. Emulator can be found under 115 | `$PE_ANDROID_ROOT/out/target/product/generic_x86_64/`. 116 | 117 | --------------------------------------------------------------------------------