# OS Changes

In order for PCS to work, there must exist a system-wide “poynt” user with special privileges. This requires the following framework-level changes:

  1. Add Poynt User ID and give necessary permissions
    1. Give poynt user protected broadcast privileges
    2. Give poynt user permission to start services
    3. Give poynt user privileged flags during package install
    4. Give poynt user access to the second screen
  2. Update rules in sepolicy files
  3. Add Poynt Settings tile to Quick Launch menu
  4. Bundling Poynt APKs

# Add Poynt User ID

Create a POYNT_UID defintion in android.os.Process with value 2500 :

frameworks/base/core/java/android/os/Process.java

Example diff:

--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -148,6 +148,12 @@
      */
     public static final int SHARED_RELRO_UID = 1037;

+    /**
+     * Defines the UID/GID for Poynt service processes.
+     * @hide
+     */
+    public static final int POYNT_UID = 2500;
+
     /**
      * Defines the start of a range of UIDs (and GIDs), going from this
      * number to {@link #LAST_APPLICATION_UID} that are reserved for assigning

# Give poynt user protected broadcast privileges

Modify the activity manager service to allow the poynt user to send protected broadcasts.

The following file must be modified:

(Kitkat):

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

(Lollipop and above):

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

Example diff:

--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -18364,6 +18364,7 @@
         int callingAppId = UserHandle.getAppId(callingUid);
         if (callingAppId == Process.SYSTEM_UID || callingAppId == Process.PHONE_UID
             || callingAppId == Process.SHELL_UID || callingAppId == Process.BLUETOOTH_UID
+            || callingAppId == Process.POYNT_UID
             || callingAppId == Process.NFC_UID || callingUid == 0) {
             // Always okay.
         } else if (callerApp == null || !callerApp.persistent) {

# Give poynt user permission to start services

Modify the activity manager to allow poynt user to start services.

This change is only needed for Lollipop and above:

frameworks/base/core/java/android/app/ActivityManager.java

Example diff:

--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2660,7 +2660,8 @@
             int owningUid, boolean exported) {
         // Root, system server get to do everything.
         final int appId = UserHandle.getAppId(uid);
-        if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
+        if (appId == Process.ROOT_UID || appId == Process.POYNT_UID
+                                      || appId == Process.SYSTEM_UID) {
             return PackageManager.PERMISSION_GRANTED;
         }
         // Isolated processes don't get any permissions.

# Give poynt user privileged flags during package install

Modify the package manager service to add privileged flags to applications installed with the poynt user ID.

The following file must be modified: (Kitkat):

frameworks/base/services/java/com/android/server/pm/PackageManagerService.java

(Lollipop and above):

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

Example diff:

--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -315,6 +315,7 @@
     private static final int NFC_UID = Process.NFC_UID;
     private static final int BLUETOOTH_UID = Process.BLUETOOTH_UID;
     private static final int SHELL_UID = Process.SHELL_UID;
+    private static final int POYNT_UID = Process.POYNT_UID;

     // Cap the size of permission trees that 3rd party apps can define
     private static final int MAX_PERMISSION_TREE_FOOTPRINT = 32768;     // characters of text
@@ -1926,6 +1927,8 @@
                 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
         mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
                 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+        mSettings.addSharedUserLPw("android.uid.poynt", POYNT_UID,
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

         // TODO: add a property to control this?
         long dexOptLRUThresholdInMinutes;

# Give poynt user access to the second screen

Modify the display manager to give poynt user ID access to the second screen (if second screen is available).

The following files must be modified:

frameworks/base/core/java/android/view/Display.java

frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java

Example diff:

diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 71916c7..67dc4bc 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -799,6 +799,7 @@
         return (flags & Display.FLAG_PRIVATE) == 0
                 || uid == ownerUid
                 || uid == Process.SYSTEM_UID
+                || uid == Process.POYNT_UID
                 || uid == 0;
     }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 83a8803..1aa0116 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -399,7 +399,7 @@


                 if (info.hasAccess(callingUid)) {
-                    if( callingUid == Process.SYSTEM_UID  ){
+                    if( callingUid == Process.SYSTEM_UID || callingUid == Process.POYNT_UID ){
                         DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
                         DisplayDeviceInfo device_info = device.getDisplayDeviceInfoLocked();
                         if ( device_info.sharedUid != 0 ) {
@@ -958,7 +958,8 @@
         final long token = Binder.clearCallingIdentity();
         try {
             // only allow access to system apps to set the uid.
-            if( callingUid == Process.SYSTEM_UID  ){
+            if( callingUid == Process.SYSTEM_UID
+             || callingUid == Process.POYNT_UID ){
                 synchronized (mSyncRoot) {
                     LogicalDisplay display = mLogicalDisplays.get(displayId);
                     if ( display != null ){
@@ -992,7 +993,9 @@
         // Find the logical display that the display device is showing.
         // Certain displays only ever show their own content.
         LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
-        if ((!ownContent) || info.ownerUid == 0 || info.ownerUid == Process.SYSTEM_UID) {
+        if ((!ownContent) || info.ownerUid == 0
+            || info.ownerUid == Process.POYNT_UID
+            || info.ownerUid == Process.SYSTEM_UID) {
             if (display != null && !display.hasContentLocked()) {
                 // If the display does not have any content of its own, then
                 // automatically mirror the default logical display contents.
@@ -1517,7 +1520,7 @@
                 }
             }

-            if (callingUid != Process.SYSTEM_UID &&
+            if (!(callingUid == Process.SYSTEM_UID || callingUid == Process.POYNT_UID) &&
                     (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
                 if (!canProjectVideo(projection)) {
                     throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "

# Update rules in sepolicy files

To allow Poynt System Services to set/update Poynt system properties the following rules must be added to the sepolicy files as below.

For Android 4.4 - 7.0:

external/sepolicy/system_app.teexternal/sepolicy/service_contexts

For Android 8.0 and higher, the following files must be modified:

system/sepolicy/public/domain.te

system/sepolicy/public/system_app.te

system/sepolicy/prebuilts/api/<target_api>/public/domain.te

system/sepolicy/prebuilts/api/<target_api>/public/system_app.te

system/sepolicy/private/service_contexts

system/sepolicy/prebuilts/api/<target_api>/private/service_contexts

system/sepolicy/private/seapp_contexts

system/sepolicy/prebuilts/api/<target_api>/private/seapp_contexts

Example diff:

diff --git a/prebuilts/api/28.0/public/domain.te b/prebuilts/api/28.0/public/domain.te
index 414073d..4274b1c 100644
--- a/prebuilts/api/28.0/public/domain.te
+++ b/prebuilts/api/28.0/public/domain.te
@@ -533,11 +533,11 @@

 # Require that domains explicitly label unknown properties, and do not allow
 # anyone but init to modify unknown properties.
-neverallow { domain -init -vendor_init } default_prop:property_service set;
+neverallow { domain -init -vendor_init -system_app } default_prop:property_service set;

 compatible_property_only(`
-    neverallow { domain -init } default_prop:property_service set;
+    neverallow { domain -init -system_app } default_prop:property_service set;

diff --git a/prebuilts/api/28.0/public/system_app.te b/prebuilts/api/28.0/public/system_app.te
index f643513..c6f20d4 100644
--- a/prebuilts/api/28.0/public/system_app.te
+++ b/prebuilts/api/28.0/public/system_app.te
@@ -7,3 +7,5 @@
 type system_app, domain;
 allow system_app nlpre_apk:dir search;
 allow system_app nlpre_apk:file { open read };
+#allow set default to properties
+allow system_app default_prop:property_service { set };

diff --git a/public/domain.te b/public/domain.te
index 414073d..4274b1c 100644
--- a/public/domain.te
+++ b/public/domain.te
@@ -533,11 +533,11 @@

 # Require that domains explicitly label unknown properties, and do not allow
 # anyone but init to modify unknown properties.
-neverallow { domain -init -vendor_init } default_prop:property_service set;
+neverallow { domain -init -vendor_init -system_app } default_prop:property_service set;

 compatible_property_only(`
-    neverallow { domain -init } default_prop:property_service set;
+    neverallow { domain -init -system_app } default_prop:property_service set;

diff --git a/public/system_app.te b/public/system_app.te
index f643513..c6f20d4 100644
--- a/public/system_app.te
+++ b/public/system_app.te
@@ -7,3 +7,5 @@
 type system_app, domain;
 allow system_app nlpre_apk:dir search;
 allow system_app nlpre_apk:file { open read };
+#allow set default to properties
+allow system_app default_prop:property_service { set };

diff --git a/system_app.te b/system_app.te
index 319dc8e..8f1a335 100644
--- a/system_app.te
+++ b/system_app.te
@@ -71,6 +71,7 @@
 allow system_app system_app_service:service_manager add;
+allow system_app default_android_service:service_manager add;

diff --git a/service_contexts b/service_contexts
index 3ffe9d3..3572bfb 100644
--- a/service_contexts
+++ b/service_contexts
@@ -124,3 +124,5 @@
 security_processor_service                u:object_r:system_server_service:s0
 barcode_decode_service                    u:object_r:system_server_service:s0
 *                                         u:object_r:default_android_service:s0
+co.poynt.device.manager.service.INetworkStatsService   u:object_r:system_app_service:s0
+PoyntNetworkStats u:object_r:system_app_service:s0

diff --git a/private/seapp_contexts b/private/seapp_contexts
index dcac495..47c51f0 100644
--- a/private/seapp_contexts
+++ b/private/seapp_contexts
@@ -92,8 +92,8 @@
 neverallow user=shell domain=((?!shell).)*

 # only the package named com.android.shell can run in the shell domain
-neverallow domain=shell name=((?!com\.android\.shell).)*
-neverallow user=shell name=((?!com\.android\.shell).)*
+neverallow domain=shell name=((?!com\.android\.shell|co\.poynt|com\.poynt).)*
+neverallow user=shell name=((?!com\.android\.shell|co\.poynt|com\.poynt).)*

 # Ephemeral Apps must run in the ephemeral_app domain
 neverallow isEphemeralApp=true domain=((?!ephemeral_app).)*
@@ -107,6 +107,10 @@
+user=shell seinfo=platform domain=shell name=com.poynt.diagnostics type=shell_data_file
+user=shell seinfo=platform domain=shell name=co.poynt.checkin type=shell_data_file
+user=shell seinfo=platform domain=shell name=co.poynt.checkin:crashtracker type=shell_data_file
+user=shell seinfo=platform domain=shell name=com.poynt.updater type=shell_data_file

diff --git a/prebuilts/api/28.0/private/seapp_contexts b/prebuilts/api/28.0/private/seapp_contexts
index dcac495..41a38c0 100644
--- a/prebuilts/api/28.0/private/seapp_contexts
+++ b/prebuilts/api/28.0/private/seapp_contexts
@@ -92,8 +92,8 @@
 neverallow user=shell domain=((?!shell).)*

 # only the package named com.android.shell can run in the shell domain
-neverallow domain=shell name=((?!com\.android\.shell).)*
-neverallow user=shell name=((?!com\.android\.shell).)*
+neverallow domain=shell name=((?!com\.android\.shell|co\.poynt|com\.poynt).)*
+neverallow user=shell name=((?!com\.android\.shell|co\.poynt|com\.poynt).)*

 # Ephemeral Apps must run in the ephemeral_app domain
 neverallow isEphemeralApp=true domain=((?!ephemeral_app).)*
@@ -107,6 +107,10 @@
 user=radio seinfo=platform domain=radio type=radio_data_file
 user=shared_relro domain=shared_relro
 user=shell seinfo=platform domain=shell name=com.android.shell type=shell_data_file
+user=shell seinfo=platform domain=shell name=com.poynt.diagnostics type=shell_data_file
+user=shell seinfo=platform domain=shell name=co.poynt.checkin type=shell_data_file
+user=shell seinfo=platform domain=shell name=co.poynt.checkin:crashtracker type=shell_data_file
+user=shell seinfo=platform domain=shell name=com.poynt.updater type=shell_data_file

# Add Poynt Settings tile to Quick Launch menu

The following files must be modified:

For Android 6.0:

frameworks/base/packages/SystemUI/res/values/config.xml

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java

frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/PoyntSettingsTile.java

For Android 9.0:

frameworks/base/packages/SystemUI/res/values/config.xml

frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java

frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSHost.java

frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java

frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java

frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/PoyntSettingsTile.java

frameworks/base/proto/src/metrics_constants.proto

Example diff:

For Android 6.0

diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 123ff78..387b56a 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -119,7 +119,7 @@

     <!-- The default tiles to display in QuickSettings -->
     <string name="quick_settings_tiles_default" translatable="false">
-        wifi,bt,inversion,dnd,cell,airplane,rotation,flashlight,location,cast,hotspot
+        poyntsettings,wifi,bt,inversion,dnd,cell,airplane,rotation,flashlight,location,cast,hotspot
     </string>

     <!-- The tiles to display in QuickSettings -->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 1a86bc7..a72784b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -68,6 +68,7 @@
 import com.mediatek.systemui.statusbar.policy.AudioProfileController;
 import com.mediatek.systemui.statusbar.policy.HotKnotController;
 import com.mediatek.systemui.statusbar.util.SIMHelper;
+import com.poynt.systemui.qs.tiles.PoyntSettingsTile;
 // /@}

 import java.util.ArrayList;
@@ -332,6 +333,8 @@
                 quickSettingsPlugin.customizeAddQSTile(new ApnSettingsTile(this)) != null) {
             return (ApnSettingsTile) quickSettingsPlugin.customizeAddQSTile(
                     new ApnSettingsTile(this));
+        } else if (tileSpec.equals("poyntsettings")) {
+            return new PoyntSettingsTile(this);
         }
         /// @}
         else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec);
diff --git a/packages/SystemUI/src/com/poynt/systemui/qs/tiles/PoyntSettingsTile.java b/packages/SystemUI/src/com/poynt/systemui/qs/tiles/PoyntSettingsTile.java
new file mode 100755
index 0000000..981dc33
--- /dev/null
+++ b/packages/SystemUI/src/com/poynt/systemui/qs/tiles/PoyntSettingsTile.java
@@ -0,0 +1,66 @@
+package com.poynt.systemui.qs.tiles;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ComponentName;
+import android.media.AudioManager;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
+import com.android.systemui.FontSizeUtils;
+import com.android.systemui.qs.QSTile;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PoyntSettingsTile extends QSTile<QSTile.BooleanState> {
+    private static final String TAG = "PoyntSettingsTile";
+    private static final boolean DBG = true;
+
+    public PoyntSettingsTile(Host host) {
+        super(host);
+    }
+
+    @Override
+    protected BooleanState newTileState() {
+        return new BooleanState();
+    }
+
+    @Override
+    public void setListening(boolean listening) {
+    }
+
+    @Override
+    protected void handleClick() {
+        Intent intent = new Intent();
+        intent.setComponent(new ComponentName(
+                "co.poynt.services",
+                "co.poynt.services.settings.SettingsActivity"));
+        mHost.startActivityDismissingKeyguard(intent);
+    }
+
+    @Override
+    protected void handleUpdateState(BooleanState state, Object arg) {
+        state.label = mContext.getString(R.string.status_bar_settings_settings_button);
+        state.visible = true;
+        state.icon = ResourceIcon.get(R.drawable.ic_settings);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_PANEL;
+    }
+
+}

For Android 9.0

diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 2f0f5c9..38cfec1 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -123,7 +123,7 @@

     <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
     <string name="quick_settings_tiles_stock" translatable="false">
-        wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night
+        poyntsettings,wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night
     </string>

diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index 0a26d2b..37173fc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -18,6 +18,7 @@

 import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;

+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.UserInfo;
@@ -368,8 +369,18 @@
     }

     private void startSettingsActivity() {
-        mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
-                true /* dismissShade */);
+        Intent intent = new Intent();
+        intent.setComponent(
+                new ComponentName(
+                        "co.poynt.services",
+                        "co.poynt.services.settings.SettingsActivity"
+                )
+        );
+
+        mActivityStarter.startActivity(
+                intent,
+                true /* dismissShade */
+        );
     }

     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
index 84524a6..bdd834e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
@@ -15,6 +15,7 @@
 package com.android.systemui.qs;

 import android.content.Context;
+import android.content.Intent;

 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.qs.external.TileServices;
@@ -35,6 +36,8 @@

     int indexOf(String tileSpec);

+    void startActivity(final Intent intent);
+
     interface Callback {
         void onTilesChanged();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 02937d8..d68a1c8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -325,4 +325,9 @@
         }
         return tiles;
     }
+
+    @Override
+    public void startActivity(final Intent intent) {
+        mStatusBar.startActivity(intent, false);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index ac 7ef5d..185e9f4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -44,6 +44,8 @@
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.util.leak.GarbageMonitor;

+import com.poynt.systemui.qs.tiles.PoyntSettingsTile;
+
 public class QSFactoryImpl implements QSFactory {

     private static final String TAG = "QSFactory";
@@ -98,6 +100,8 @@
                 return new NightDisplayTile(mHost);
             case "nfc":
                 return new NfcTile(mHost);
+            case "poyntsettings":
+                return new PoyntSettingsTile(mHost);
         }

         // Intent tiles.
diff --git a/packages/SystemUI/src/com/poynt/systemui/qs/tiles/PoyntSettingsTile.java b/packages/SystemUI/src/com/poynt/systemui/qs/tiles/PoyntSettingsTile.java
new file mode 100755
index 0000000..109f691
--- /dev/null
+++ b/packages/SystemUI/src/com/poynt/systemui/qs/tiles/PoyntSettingsTile.java
@@ -0,0 +1,62 @@
+package com.poynt.systemui.qs.tiles;
+
+import android.content.*;
+import android.nfc.NfcAdapter;
+import android.provider.Settings;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+
+public class PoyntSettingsTile extends QSTileImpl<BooleanState> {
+    private static final String TAG = "PoyntSettingsTile";
+
+    public PoyntSettingsTile(QSHost host) {
+        super(host);
+    }
+
+    @Override
+    public BooleanState newTileState() {
+        return new BooleanState();
+    }
+
+    @Override
+    public CharSequence getTileLabel() {
+        return mContext.getString(R.string.status_bar_settings_settings_button);
+    }
+
+    @Override
+    public void handleSetListening(boolean listening) {
+    }
+
+    @Override
+    protected void handleClick() {
+        Intent intent = new Intent();
+        intent.setComponent(
+                new ComponentName(
+                        "co.poynt.services",
+                        "co.poynt.services.settings.SettingsActivity"
+                )
+        );
+
+        mHost.startActivity(intent);
+    }
+
+    @Override
+    public Intent getLongClickIntent() {
+        return new Intent(Settings.ACTION_AIRPLANE_MODE_SETTINGS);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsEvent.QS_POYNT_SETTINGS;
+    }
+
+    @Override
+    protected void handleUpdateState(BooleanState state, Object arg) {
+        state.label = mContext.getString(R.string.status_bar_settings_settings_button);
+        state.icon = ResourceIcon.get(R.drawable.ic_settings);
+    }
+
+}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 4328d94..9a6a16e 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -6116,6 +6116,8 @@
     // OS: P
     FIELD_AUTOFILL_SESSION_ID = 1456;

+    QS_POYNT_SETTINGS = 1457;
+
     // ---- End P Constants, all P constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS

# Bundling Poynt APKs

Once the above mentioned code changes are done, next step is to bundle Poynt App bundle that includes all Poynt System Services and applications necessary to enable Poynt ecosystem on your device.

Bundling Poynt APKs involved the following:

  1. Create a vendor folder for Poynt in your AOSP source repository and include the Poynt modules in your device specific *.mk file

    Eg. For a Qualcomm based device it would be: qcom/msm8909/msm8909.mk

    -include vendor/poynt/prebuilts/poyntmodules.mk
    
  2. Download the Poynt APK bundle and extract in to the vendor folder for Poynt

    Eg.

    vendor/poynt/prebuilts
    
  3. Build your OS and confirm the Poynt APKs copied into /system/app and /system/priv-app folders

    Eg. For a Qualcomm based device:

    out/target/product/msm8909/system/app
    out/target/product/msm8909/system/priv-app
    

# Application Signing

Some of the Poynt System Applications require to be signed by your platform key to have the System or Signature permissions that are necessary for them to provide the functionality needed for the Poynt ecosystem. These applications are configured in the Android.mk in the downloaded bundle to be signed with your platform key.

Eg.

LOCAL_MODULE := PoyntSystemUpdater
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_PATH := $(TARGET_OUT_APPS_PRIVILEGED)
LOCAL_SRC_FILES := $(LOCAL_MODULE)$(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := platform

At the moment the following 3 Poynt system applications are configured for platform signing (please refer to the section on Poynt Apps to know more about these applications):

  1. PoyntSystemUpdater
  2. PoyntCheckinService
  3. PoyntAccessoryManager

All other applications are PRE-SIGNED and should not be resigned by your platform keys.

Last Updated: 10/1/2020, 12:42:00 AM