# 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. Add system property indicating your OS is Poynt compatible in your system build.prop
    1. ro.poynt.compatible=true
  5. 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

For Android 10:

system/sepolicy/prebuilts/api/<target_api>/private/priv_app.te

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

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

system/sepolicy/private/priv_app.te

system/sepolicy/private/seapp_contexts

system/sepolicy/public/domain.te

For collecting logs and uploading to poynt servers:

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

system/sepolicy/public/shell.te

Example diff:

diff --git a/prebuilts/api/29.0/private/priv_app.te b/prebuilts/api/29.0/private/priv_app.te
index 2dda0b3c..6448c26c 100755
--- a/prebuilts/api/29.0/private/priv_app.te
+++ b/prebuilts/api/29.0/private/priv_app.te
@@ -213,9 +213,9 @@ neverallow priv_app service_manager_type:service_manager add;
 
 # Do not allow privileged apps to connect to the property service
 # or set properties. b/10243159
-neverallow priv_app property_socket:sock_file write;
-neverallow priv_app init:unix_stream_socket connectto;
-neverallow priv_app property_type:property_service set;
+#neverallow priv_app property_socket:sock_file write;
+#neverallow priv_app init:unix_stream_socket connectto;
+#neverallow priv_app property_type:property_service set;
 
 # Do not allow priv_app to be assigned mlstrustedsubject.
 # This would undermine the per-user isolation model being
@@ -253,3 +253,9 @@ neverallow priv_app app_data_file:file no_x_file_perms;
 neverallow priv_app app_data_file:lnk_file { open read getattr };

 allow priv_app zygote:binder { call transfer };
+
+allow priv_app default_prop:property_service { set };
+allow priv_app property_socket:sock_file { write };
+allow priv_app init:unix_stream_socket connectto;
+allow priv_app system_prop:property_service set;

diff --git a/prebuilts/api/29.0/private/seapp_contexts b/prebuilts/api/29.0/private/seapp_contexts
index 0ef80091..bfa2d1d4 100755
--- a/prebuilts/api/29.0/private/seapp_contexts
+++ b/prebuilts/api/29.0/private/seapp_contexts
@@ -169,3 +169,4 @@ user=shell seinfo=platform domain=shell name=com.poynt.diagnostics type=shell_da
 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
+user=poynt isPrivApp=true domain=priv_app type=privapp_data_file levelFrom=all

diff --git a/prebuilts/api/29.0/public/domain.te b/prebuilts/api/29.0/public/domain.te
index 86f1f02b..63ce9480 100755
--- a/prebuilts/api/29.0/public/domain.te
+++ b/prebuilts/api/29.0/public/domain.te
@@ -522,11 +522,11 @@ neverallow * hidl_base_hwservice:hwservice_manager find;
 
 # Require that domains explicitly label unknown properties, and do not allow
 # anyone but init to modify unknown properties.
-neverallow { domain -init -vendor_init -system_app -system_server -zygote} default_prop:property_service set;
+neverallow { domain -init -vendor_init -system_app -system_server -zygote -priv_app } default_prop:property_service set;
 neverallow { domain -init -vendor_init } mmc_prop:property_service set;
 
 compatible_property_only(

-neverallow { domain -init -system_app -system_server -zygote} default_prop:property_service set;
+neverallow { domain -init -system_app -system_server -zygote -priv_app } default_prop:property_service set;

     neverallow { domain -init } mmc_prop:property_service set;
     neverallow { domain -init -vendor_init } exported_default_prop:property_service set;
     neverallow { domain -init } exported_secure_prop:property_service set;

@@ -1127,6 +1127,7 @@ neverallow * {
   -asec_public_file
   -zygote
   -system_file
+  -priv_app
 }:file execmod;
 
 # Do not allow making the stack or heap executable.
@@ -1136,7 +1137,7 @@ neverallow * self:process { execstack execheap };
 
 # Do not allow the introduction of new execmod rules. Text relocations
 # and modification of executable pages are unsafe.
-neverallow { domain -untrusted_app_25 -untrusted_app_27 -zygote } file_type:file execmod;
+neverallow { domain -untrusted_app_25 -untrusted_app_27 -zygote -priv_app } file_type:file execmod;
 
 neverallow { domain -init } proc:{ file dir } mounton;


diff --git a/private/priv_app.te b/private/priv_app.te
index 2dda0b3c..6448c26c 100755
--- a/private/priv_app.te
+++ b/private/priv_app.te
@@ -213,9 +213,9 @@ neverallow priv_app service_manager_type:service_manager add;
 
 # Do not allow privileged apps to connect to the property service
 # or set properties. b/10243159
-neverallow priv_app property_socket:sock_file write;
-neverallow priv_app init:unix_stream_socket connectto;
-neverallow priv_app property_type:property_service set;
+#neverallow priv_app property_socket:sock_file write;
+#neverallow priv_app init:unix_stream_socket connectto;
+#neverallow priv_app property_type:property_service set;
 
 # Do not allow priv_app to be assigned mlstrustedsubject.
 # This would undermine the per-user isolation model being
@@ -253,3 +253,9 @@ neverallow priv_app app_data_file:file no_x_file_perms;
 neverallow priv_app app_data_file:lnk_file { open read getattr };
 
 allow priv_app zygote:binder { call transfer };
+
+allow priv_app default_prop:property_service { set };
+allow priv_app property_socket:sock_file { write };
+allow priv_app init:unix_stream_socket connectto;
+allow priv_app system_prop:property_service set;


diff --git a/private/seapp_contexts b/private/seapp_contexts
index 0ef80091..bfa2d1d4 100755
--- a/private/seapp_contexts
+++ b/private/seapp_contexts
@@ -169,3 +169,4 @@ user=shell seinfo=platform domain=shell name=com.poynt.diagnostics type=shell_da
 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
+user=poynt isPrivApp=true domain=priv_app type=privapp_data_file levelFrom=all


diff --git a/public/domain.te b/public/domain.te
index 86f1f02b..63ce9480 100755
--- a/public/domain.te
+++ b/public/domain.te
@@ -522,11 +522,11 @@ neverallow * hidl_base_hwservice:hwservice_manager find;
 
 # Require that domains explicitly label unknown properties, and do not allow
 # anyone but init to modify unknown properties.
-neverallow { domain -init -vendor_init -system_app -system_server -zygote} default_prop:property_service set;
+neverallow { domain -init -vendor_init -system_app -system_server -zygote -priv_app } default_prop:property_service set;
 neverallow { domain -init -vendor_init } mmc_prop:property_service set;
 
 compatible_property_only(
-    neverallow { domain -init -system_app -system_server -zygote} default_prop:property_service set;
+    neverallow { domain -init -system_app -system_server -zygote -priv_app } default_prop:property_service set;
     neverallow { domain -init } mmc_prop:property_service set;
     neverallow { domain -init -vendor_init } exported_default_prop:property_service set;
     neverallow { domain -init } exported_secure_prop:property_service set;
@@ -1127,6 +1127,7 @@ neverallow * {
   -asec_public_file
   -zygote
   -system_file
+  -priv_app
 }:file execmod;
 
 # Do not allow making the stack or heap executable.
@@ -1136,7 +1137,7 @@ neverallow * self:process { execstack execheap };
 
 # Do not allow the introduction of new execmod rules. Text relocations
 # and modification of executable pages are unsafe.
-neverallow { domain -untrusted_app_25 -untrusted_app_27 -zygote } file_type:file execmod;
+neverallow { domain -untrusted_app_25 -untrusted_app_27 -zygote -priv_app } file_type:file execmod;
 
 neverallow { domain -init } proc:{ file dir } mounton;

 
diff --git a/system/sepolicy/prebuilts/api/29.0/public/shell.te b/system/sepolicy/prebuilts/api/29.0/public/shell.te
index ed65b73..7e18c2a 100644
--- a/system/sepolicy/prebuilts/api/29.0/public/shell.te
+++ b/system/sepolicy/prebuilts/api/29.0/public/shell.te
@@ -72,7 +72,7 @@
 # property (which also takes care of /data/misc initialization).
 set_prop(shell, traced_enabled_prop)
 # adjust is_loggable properties
-userdebug_or_eng('set_prop(shell, log_prop)')
+set_prop(shell, log_prop)
 # logpersist script
 

diff --git a/system/sepolicy/public/shell.te b/system/sepolicy/public/shell.te
index ed65b73..7e18c2a 100644
--- a/system/sepolicy/public/shell.te
+++ b/system/sepolicy/public/shell.te
@@ -72,7 +72,7 @@
 # property (which also takes care of /data/misc initialization).
 set_prop(shell, traced_enabled_prop)
 # adjust is_loggable properties
-userdebug_or_eng('set_prop(shell, log_prop)')
+set_prop(shell, log_prop)
 # logpersist script
 userdebug_or_eng(set_prop(shell, logpersistd_logging_prop)')
 # Allow shell to start/stop heapprofd via the persist.heapprofd.enable

 

Android 13 - A/B(Seamless) System Updates

Below Sepolicy Changes for Shell and Update_Engine Context

/system/sepolicy/public/update_engine.te

/system/sepolicy/prebuilts/32.0/public/update_engine.te


allow update_engine fuse:dir search;

/system/sepolicy/public/shell.te

/system/sepolicy/prebuilts/32.0/public/shell.te


allow shell update_engine:binder call;

# 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.

# Add Poynt Bundle ID system property

Every time a new PCS Bundle is released, it will be assigned a version of the format YYMMDD. This must be defined as a system property: 'ro.build.poynt_bundle_id' so other apps can identify the PCS bundle compatibility as needed.

Add the below line to the file system/sepolicy/private/property_contexts:

"ro.build.poynt_bundle_id u:object_r:vendor_default_prop:s0"

This will add the system property as a vendor default property.

# Whitelist System|Sign Permissions

Poynt Appplication Bundle will contain a XML named privapp-permissions-poynt.xml . This is an exclusive XML file, required to be loaded in /system/etc/permission folder. This will ensure the granting of mentioned SignatureOrSystem permissions to mentioned priviledge applications.

For example, below xml snippet will be used to grant SigantureOrSystem permissions for priv-app package "com.poynt.updater".

 <privapp-permissions package="com.poynt.updater">
        <permission name="android.permission.ACCESS_CACHE_FILESYSTEM"/>
        <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
        <permission name="android.permission.REBOOT"/>
        <permission name="android.permission.RECOVERY"/>
        <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
        <permission name="android.permission.INTERACT_ACROSS_USERS"/>
        <permission name="android.permission.CHANGE_OVERLAY_PACKAGES"/>
        <permission name="android.permission.MODIFY_QUIET_MODE"/>
        <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
        <permission name="android.permission.DELETE_CACHE_FILES"/>
        <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
        <permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/>
    </privapp-permissions>

# Adding Custom Poynt Logtags

Custom Event Tags for system verified Event Logs. These Event Logs are used to track the Poynt Specific Lifecycles . PCS bundle will have a file named "poynt.logtags" on path "apps/". Sample "poynt.logtags" contemnts are as below .

# Poynt
99966 poynt_no_sale_triggered (username|3),(role|3),(status|1),(session_id|3)
99967 poynt_accessory_connected   (package|3),(type|3),(vid|1),(pid|1),(ssid|3)
99968 poynt_accessory_disconnected (package|3),(type|3),(vid|1),(pid|1),(ssid|3)
99969 poynt_accessory_registered (package|3),(type|3),(vid|1),(pid|1),(ssid|3)
99970 poynt_accessory_unregistered (package|3),(type|3),(vid|1),(pid|1),(ssid|3)
99971 poynt_printer_status (status|3),(session_id|3)
99972 poynt_websocket_connectivity_changed (status|3),(type|3)
99973 poynt_pci_security_not_enabled
# 1 for loaded, 0 otherwise
99974 poynt_card_reader_config_msr_loaded (state|1|5)
99975 poynt_card_reader_config_cl_loaded (state|1|5)

For above changes to work, vendor filtering need to removed during merge logtags task. Removing the vendor filtering will ensure the custom logtags to be added to merged logtags list.

build/make/core/Makefile

# -----------------------------------------------------------------

.PHONY: event-log-tags

# Produce an event logs tag file for everything we know about, in order
# to properly allocate numbers.  Then produce a file that's filtered
# for what's going to be installed.

all_event_log_tags_file := $(TARGET_OUT_COMMON_INTERMEDIATES)/all-event-log-tags.txt

event_log_tags_file := $(TARGET_OUT)/etc/event-log-tags

# Include tags from all packages that we know about
all_event_log_tags_src := \
    $(sort $(foreach m, $(ALL_MODULES), $(ALL_MODULES.$(m).EVENT_LOG_TAGS)))

$(all_event_log_tags_file): PRIVATE_SRC_FILES := $(all_event_log_tags_src)
$(all_event_log_tags_file): $(all_event_log_tags_src) $(MERGETAGS) build/make/tools/event_log_tags.py
	$(hide) mkdir -p $(dir $@)
	$(hide) $(MERGETAGS) -o $@ $(PRIVATE_SRC_FILES)

# Include tags from all packages included in this product, plus all
# tags that are part of the system (ie, not in a vendor/ or device/
# directory).
event_log_tags_src := \
    $(sort $(foreach m,\
      $(call resolve-bitness-for-modules,TARGET,$(PRODUCT_PACKAGES)) \
      $(call module-names-for-tag-list,user), \
      $(ALL_MODULES.$(m).EVENT_LOG_TAGS)) \
  --   $(filter-out vendor/% device/% out/%,$(all_event_log_tags_src)))
  ++    $(filter-out device/% out/%,$(all_event_log_tags_src)))

Last Updated: 7/31/2024, 8:21:40 AM