diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index cd2c12cb4b6f221872ffdcf78dc70f9f957ba636..9a1051a5c1e835f40c08d39cb54ab2f42b9062a8 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -123,6 +123,8 @@ import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.UserIcons;
 
+import com.nvidia.NvAppProfileService;
+
 import dalvik.system.VMRuntime;
 
 import libcore.util.EmptyArray;
@@ -175,6 +177,7 @@ public class ApplicationPackageManager extends PackageManager {
     private PermissionManager mPermissionManager;
     @GuardedBy("mLock")
     private PackageInstaller mInstaller;
+    private NvAppProfileService mAppProfileService;
     @GuardedBy("mLock")
     private ArtManager mArtManager;
 
@@ -435,6 +438,15 @@ public class ApplicationPackageManager extends PackageManager {
                 com.android.internal.R.bool.config_wirelessConsentRequired);
     }
 
+    /** @hide */
+    @Override
+    public NvAppProfileService getAppProfileService() {
+        if (mAppProfileService == null) {
+            mAppProfileService = new NvAppProfileService(mContext);
+        }
+        return mAppProfileService;
+    }
+
     @Override
     public ApplicationInfo getApplicationInfo(String packageName, int flags)
             throws NameNotFoundException {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a6bf6a41e7565af7b5676529a0df5f447c390ad4..f58af0e6f1c925d016f8f6b097ccff1565213577 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -84,6 +84,8 @@ import android.util.Log;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 
+import com.nvidia.NvAppProfileService;
+
 import dalvik.system.VMRuntime;
 
 import java.lang.annotation.Retention;
@@ -4699,6 +4701,11 @@ public abstract class PackageManager {
     public abstract List<PermissionGroupInfo> getAllPermissionGroups(
             @PermissionGroupInfoFlags int flags);
 
+    /** @hide */
+    public NvAppProfileService getAppProfileService() {
+        return null;
+    }
+
     /**
      * Get the platform-defined permissions which belong to a particular permission group.
      *
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 4ff26242dab2beae2e6e77964c7bf1172c75b685..86fef5d9df19d6f31135e4cf23254070d0e8f118 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -96,6 +96,8 @@ import com.android.internal.os.ClassLoaderFactory;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
 
+import com.nvidia.NvAppProfileService;
+
 import libcore.io.IoUtils;
 import libcore.util.EmptyArray;
 import libcore.util.HexEncoding;
@@ -601,6 +603,7 @@ public class PackageParser {
      * a package.
      */
     public interface Callback {
+        NvAppProfileService getAppProfileService();
         boolean hasFeature(String feature);
     }
 
@@ -615,6 +618,10 @@ public class PackageParser {
             mPm = pm;
         }
 
+        @Override public NvAppProfileService getAppProfileService() {
+            return mPm.getAppProfileService();
+        }
+
         @Override public boolean hasFeature(String feature) {
             return mPm.hasSystemFeature(feature);
         }
diff --git a/core/java/com/nvidia/NvAppProfileService.java b/core/java/com/nvidia/NvAppProfileService.java
new file mode 100644
index 0000000000000000000000000000000000000000..694c4bd663db8e94bd2f7561e6595211a89a5bdb
--- /dev/null
+++ b/core/java/com/nvidia/NvAppProfileService.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2012 - 2014 NVIDIA Corporation.  All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Class structure based upon Camera in Camera.java:
+ * Copyright (C) 2009 The Android Open Source Project
+ */
+
+package com.nvidia;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.nvidia.profilemanager.NvAppProfileSettingId;
+
+/**
+ * @hide
+ */
+public class NvAppProfileService {
+    private static final String TAG = "NvAppProfileService";
+    private static final String APP_START_ACTION =
+            "com.nvidia.NvAppProfileService.action.APP_START";
+    private static final String APP_START_TARGET_PACKAGE = "com.nvidia.peripheralservice";
+    private static final String FEATURE_POWER_BUDGET_CONTROL =
+            "nvidia.feature.power_budget_control";
+    private static final String FEATURE_FAN_ON_DEVICE = "nvidia.feature.fan_on_device";
+
+    private final NvAppProfiles mAppProfile;
+    private final NvWhitelistService mWhitelistService;
+    private final Context mContext;
+
+    private boolean mInitialisedAppProfiles = false;
+    private boolean mFanCapEnabled = false;
+    private boolean mPbcEnabled = false;
+
+    public NvAppProfileService(Context context) {
+        Context appContext = context.getApplicationContext();
+        if (appContext == null) {
+            mContext = context;
+        } else {
+            mContext = appContext;
+        }
+
+        mAppProfile = new NvAppProfiles(mContext);
+        mWhitelistService = new NvWhitelistService(mContext);
+    }
+
+    private static String getPackageName(String appName) {
+        int index = appName.indexOf('/');
+        if (index < 0) {
+            Log.e(TAG, "appName does not contain '/'. " +
+                    "The packageName cannot be extracted from appName!");
+            return null;
+        }
+        return appName.substring(0, index);
+    }
+
+    /*
+     * These are functions that depend on NvAppProfiles and may or may not
+     * be supported for certain platforms. In the latter case, these methods
+     * should return -1.
+     */
+    public boolean getAppProfileFRCEnable(String packageName) {
+        return packageName != null && mAppProfile.getApplicationProfile(packageName,
+                NvAppProfileSettingId.VIDEO_FRC_ENABLE) == 1;
+    }
+
+    public boolean getAppProfileCreateSecureDecoder(String packageName) {
+        return packageName != null && mAppProfile.getApplicationProfile(packageName,
+                NvAppProfileSettingId.VIDEO_SECURE_DECODE) == 1;
+    }
+
+    public boolean getAppProfileTSFilterEnable(String packageName) {
+        return packageName != null && mAppProfile.getApplicationProfile(packageName,
+                NvAppProfileSettingId.VIDEO_TS_FILTERING) == 1;
+    }
+
+    public boolean getAppProfileMediaEnableMsdHal(String packageName) {
+        return packageName != null && this.mAppProfile.getApplicationProfile(packageName,
+                NvAppProfileSettingId.MEDIA_ENABLE_MSD_HAL) == 1;
+    }
+
+    public boolean getAppProfileNvidiaCertification(String packageName) {
+        return packageName != null && mAppProfile.getApplicationProfile(packageName,
+                NvAppProfileSettingId.NVIDIA_VIDEO_CERTIFICATION_ENABLED) == 1;
+    }
+
+    public String customizeAppBanner(String packageName) {
+        if (packageName == null) return null;
+
+        final String bannerName = mAppProfile.getApplicationProfileString(packageName,
+                NvAppProfileSettingId.WHITELIST_CUSTOMIZE_BANNER);
+        if (bannerName != null) return bannerName;
+
+        return mWhitelistService.getBannerName(packageName);
+    }
+
+    public Drawable getBannerDrawable(String packageName) {
+        final String bannerName = customizeAppBanner(packageName);
+        if (bannerName == null || bannerName.length() == 0) {
+            return null;
+        }
+
+        final Resources systemResources = mContext.getResources().getSystem();
+        final int drawableResourceId = systemResources.getIdentifier(bannerName,
+                "drawable", "android");
+        if (drawableResourceId == 0) return null;
+
+        return systemResources.getDrawable(drawableResourceId);
+    }
+
+    public NvWhitelistService getWhitelistService() {
+        return mWhitelistService;
+    }
+
+    public boolean getAppProfileDisableApp(String packageName) {
+        return packageName != null && mAppProfile.getApplicationProfile(packageName,
+                NvAppProfileSettingId.DISABLE_APP) == 1;
+    }
+
+    private int getAppProfileCpuScalingMinFreq(String packageName) {
+        return mAppProfile.getApplicationProfile(packageName,
+                NvAppProfileSettingId.SCALING_MIN_FREQ);
+    }
+
+    private int getAppProfileCpuCoreBias(String packageName) {
+        return mAppProfile.getApplicationProfile(packageName, NvAppProfileSettingId.CORE_BIAS);
+    }
+
+    private int getAppProfileGpuScaling(String packageName) {
+        return mAppProfile.getApplicationProfile(packageName, NvAppProfileSettingId.GPU_SCALING);
+    }
+
+    private int getAppProfileCpuMaxNormalFreq(String packageName) {
+        return mAppProfile.getApplicationProfile(packageName, NvAppProfileSettingId.CPU_FREQ_BIAS);
+    }
+
+    private int getAppProfileCpuMaxNormalFreqPercent(String packageName) {
+        return mAppProfile.getApplicationProfile(packageName,
+                NvAppProfileSettingId.MAX_CPU_FREQ_PCT);
+    }
+
+    private int getAppProfileCpuMinCore(String packageName) {
+        return mAppProfile.getApplicationProfile(packageName, NvAppProfileSettingId.MIN_CPU_CORES);
+    }
+
+    private int getAppProfileCpuMaxCore(String packageName) {
+        return mAppProfile.getApplicationProfile(packageName, NvAppProfileSettingId.MAX_CPU_CORES);
+    }
+
+    private int getAppProfileGpuCbusCapLevel(String packageName) {
+        return mAppProfile.getApplicationProfile(packageName, NvAppProfileSettingId.GPU_CORE_CAP);
+    }
+
+    private int getAppProfileEdpMode(String packageName) {
+        return mAppProfile.getApplicationProfile(packageName, NvAppProfileSettingId.EDP_MODE);
+    }
+
+    private int getAppProfilePbcPwr(String packageName) {
+        if (!mPbcEnabled) return -1;
+
+        return mAppProfile.getApplicationProfile(packageName, NvAppProfileSettingId.PBC_PWR_LIMIT);
+    }
+
+    private int getAppProfileFanCap(String packageName) {
+        if (!mFanCapEnabled) return -1;
+
+        return mAppProfile.getApplicationProfile(packageName, NvAppProfileSettingId.FAN_PWM_CAP);
+    }
+
+    private int getAppProfileVoltTempMode(String packageName) {
+        return mAppProfile.getApplicationProfile(packageName, NvAppProfileSettingId.VOLT_TEMP_MODE);
+    }
+
+    private int getAppProfileAggresivePrismEnable(String packageName) {
+        return mAppProfile.getApplicationProfile(packageName,
+                NvAppProfileSettingId.AGGRESSIVE_PRISM_ENABLE);
+    }
+
+    private int getAppProfileDevicePowerMode(String packageName) {
+        return mAppProfile.getApplicationProfile(packageName,
+                NvAppProfileSettingId.SYSTEM_POWER_MODE);
+    }
+
+    public String getAppProfileRegionEnableList(String packageName) {
+        return mAppProfile.getApplicationProfileString(packageName,
+                NvAppProfileSettingId.SET_REGION_LIST);
+    }
+
+    public int getAppProfileNvidiaBBCApps(String packageName) {
+        return mAppProfile.getApplicationProfile(packageName, NvAppProfileSettingId.BBC_APPS);
+    }
+
+    private int retrievePowerMode() {
+        final String powerMode = SystemProperties.get(NvConstants.NvPowerModeProperty);
+        if (powerMode != null) {
+            try {
+                return Integer.parseInt(powerMode);
+            } catch (NumberFormatException ex) {
+                // Fallthrough to error case
+            }
+        }
+
+        return -1;
+    }
+
+    /**
+     * Interface for the caller
+     */
+    public void setAppProfile(String packageName) {
+        // Greedy initialization of App Profiles
+        if (!mInitialisedAppProfiles) {
+            PackageManager pm = mContext.getPackageManager();
+            mPbcEnabled = pm.hasSystemFeature(FEATURE_POWER_BUDGET_CONTROL);
+            mFanCapEnabled = pm.hasSystemFeature(FEATURE_FAN_ON_DEVICE);
+
+            Log.w(TAG, "Enabled");
+            mInitialisedAppProfiles = true;
+        }
+
+        mAppProfile.powerHint(packageName);
+
+        Intent intent = new Intent(APP_START_ACTION);
+        intent.setPackage(APP_START_TARGET_PACKAGE);
+        intent.putExtra("AppStartId", packageName);
+        mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT,
+                "nvidia.permission.READ_APP_START_INFO");
+    }
+}
diff --git a/core/java/com/nvidia/NvAppProfiles.java b/core/java/com/nvidia/NvAppProfiles.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c88b725afd73535dbeed7ffa7329b02ef6971ad
--- /dev/null
+++ b/core/java/com/nvidia/NvAppProfiles.java
@@ -0,0 +1,96 @@
+package com.nvidia;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import com.nvidia.NvCPLSvc.INvCPLRemoteService;
+
+public class NvAppProfiles {
+    /**
+     * Unique name used for NvCPLSvc to whitelist this class
+     */
+    static final String NV_APP_PROFILES_NAME = "Frameworks_NvAppProfiles";
+    static final boolean DEBUG = false;
+    private static final String TAG = "NvAppProfiles";
+    private final Context mContext;
+    private INvCPLRemoteService mNvCPLSvc = null;
+    private IBinder mNvCPLSvcBinder = null;
+
+    /**
+     * Callback class given by the NvCPLService
+     */
+
+    public NvAppProfiles(Context context) {
+        mContext = context;
+    }
+
+    public int getApplicationProfile(String packageName, int settingId) {
+        getNvCPLService();
+        if (mNvCPLSvc != null) {
+            try {
+                return mNvCPLSvc.getAppProfileSettingInt(packageName, settingId);
+            } catch (RemoteException ex) {
+                Log.w(TAG, "Failed to retrieve profile setting. Error=" + ex.getMessage());
+            }
+        }
+
+        return -1;
+    }
+
+    public String getApplicationProfileString(String packageName, int settingId) {
+        getNvCPLService();
+        if (mNvCPLSvc != null) {
+            try {
+                return mNvCPLSvc.getAppProfileSettingString(packageName, settingId);
+            } catch (RemoteException ex) {
+                Log.w(TAG, "Failed to retrieve profile setting. Error=" + ex.getMessage());
+            }
+        }
+
+        return null;
+    }
+
+    public void setPowerMode(int index) {
+        if (DEBUG) Log.w(TAG, "Setting power mode: " + String.valueOf(index));
+
+        Intent intent = new Intent();
+        intent.setClassName(NvConstants.NvCPLSvc, NvConstants.NvCPLService);
+        intent.putExtra(NvConstants.NvOrigin, 1);
+        intent.putExtra(NvConstants.NvPowerMode , String.valueOf(index));
+
+        handleIntent(intent);
+    }
+
+    public void powerHint(String packageName) {
+        getNvCPLService();
+        if (mNvCPLSvc != null) {
+            try {
+                mNvCPLSvc.powerHint(packageName);
+            } catch (RemoteException ex) {
+                Log.w(TAG, "Failed to send power hint. Error=" + ex.getMessage());
+            }
+        }
+    }
+
+    public void handleIntent(Intent intent) {
+        getNvCPLService();
+        if (mNvCPLSvc != null) {
+            try {
+                mNvCPLSvc.handleIntent(intent);
+            } catch (RemoteException ex) {
+                Log.w(TAG, "Failed to handle intent. Error=" + ex.getMessage());
+            }
+        }
+    }
+
+    private void getNvCPLService() {
+        if (mNvCPLSvc == null || mNvCPLSvcBinder == null || !mNvCPLSvcBinder.isBinderAlive()) {
+            mNvCPLSvcBinder = ServiceManager.getService("nvcpl");
+            mNvCPLSvc = INvCPLRemoteService.Stub.asInterface(mNvCPLSvcBinder);
+        }
+    }
+}
diff --git a/core/java/com/nvidia/NvCPLSvc/NvAppProfile.java b/core/java/com/nvidia/NvCPLSvc/NvAppProfile.java
index 82986fbb7ca6a81fe61639f5ab03f2a05d302c7b..1486edbe45c15dd1294dce8ca23e2057fb2981f6 100644
--- a/core/java/com/nvidia/NvCPLSvc/NvAppProfile.java
+++ b/core/java/com/nvidia/NvCPLSvc/NvAppProfile.java
@@ -41,11 +41,11 @@ public class NvAppProfile implements Parcelable {
     }
 
     private static String encodeNull(String string) {
-        return string != null ? string : ProxyInfo.LOCAL_EXCL_LIST;
+        return string != null ? string : "";
     }
 
     private static String decodeNull(String string) {
-        return !string.equals(ProxyInfo.LOCAL_EXCL_LIST) ? string : null;
+        return !string.equals("") ? string : null;
     }
 
     public int describeContents() {
diff --git a/core/java/com/nvidia/NvConstants.java b/core/java/com/nvidia/NvConstants.java
new file mode 100644
index 0000000000000000000000000000000000000000..d424d4cf28b3a37c75c4534db8cbfa47cda7f522
--- /dev/null
+++ b/core/java/com/nvidia/NvConstants.java
@@ -0,0 +1,18 @@
+package com.nvidia;
+
+public class NvConstants {
+    public static final String NvAppClose = "com.nvidia.app.close";
+    public static final String NvBatteryMonitor = "com.nvidia.NvCPLSvc.BatteryMonitor";
+    public static final String NvCPLService = "com.nvidia.NvCPLSvc.NvCPLService";
+    public static final String NvCPLSvc = "com.nvidia.NvCPLSvc";
+    public static final String NvMaxGpuMode = "com.nvidia.NvCPLSvc.MaxGpuMode";
+    public static final String NvOrigin = "com.nvidia.NvCPLSvc.Origin";
+    public static final String NvPowerMode = "com.nvidia.NvCPLSvc.NV_POWER_MODE";
+    public static final String NvPowerModeProperty = "persist.vendor.sys.NV_POWER_MODE";
+    public static final String NvStateId = "com.nvidia.NvCPLSvc.StateID";
+    public static final String NvTCPDivisor = "com.nvidia.NvCPLSvc.NV_TCPDIVISOR";
+    public static final String NvThermalStats = "com.nvidia.peripheralservice.NvThermalStats";
+    public static final int NV_POWER_MODE_MAX_PERF = 0;
+    public static final int NV_POWER_MODE_OPTIMIZED = 1;
+    public static final int NV_POWER_MODE_BATTERY_SAVER = 2;
+}
diff --git a/core/java/com/nvidia/NvWhitelistService.java b/core/java/com/nvidia/NvWhitelistService.java
new file mode 100644
index 0000000000000000000000000000000000000000..dfed390ccd91692da94152e110140212d15f3178
--- /dev/null
+++ b/core/java/com/nvidia/NvWhitelistService.java
@@ -0,0 +1,112 @@
+package com.nvidia;
+
+import android.content.Context;
+import android.content.res.XmlResourceParser;
+import android.util.Log;
+
+import com.android.internal.R;
+
+import java.util.ArrayList;
+import java.io.IOException;
+
+import org.json.JSONObject;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.xmlpull.v1.XmlPullParserException;
+
+public class NvWhitelistService {
+    private static final String TAG = "NvWhitelistService";
+    private JSONArray mWhiteListArray;
+    private Context mContext;
+
+    public NvWhitelistService(Context context) {
+        Context appContext = context.getApplicationContext();
+        mContext = appContext != null ? appContext : context;
+        mWhiteListArray =
+                parseXml(mContext.getResources().getXml(R.xml.tv_launcher_app_white_list));
+    }
+
+    public boolean isWhiteApp(String pkgName) {
+        if (mWhiteListArray == null) return false;
+
+        for (int i = 0; i < mWhiteListArray.length(); i++) {
+            try {
+                if (pkgName.equals(mWhiteListArray.getJSONObject(i).getString("packageName"))) {
+                    return true;
+                }
+            } catch (JSONException ex) {
+                Log.w(TAG, ex.getMessage());
+            }
+        }
+
+        return false;
+    }
+
+    public boolean isTvGame(String pkgName) {
+        if (mWhiteListArray == null) return false;
+
+        for (int i = 0; i < mWhiteListArray.length(); i++) {
+            try {
+                if (mWhiteListArray.getJSONObject(i).getString("packageName").equals(pkgName) &&
+                        mWhiteListArray.getJSONObject(i).getString("isGame").equals("true")) {
+                    return true;
+                }
+            } catch (JSONException ex) {
+                Log.w(TAG, ex.getMessage());
+            }
+        }
+
+        return false;
+    }
+
+    public String getBannerName(String pkgName) {
+        for (int i = 0; i < mWhiteListArray.length(); i++) {
+            try {
+                if (mWhiteListArray.getJSONObject(i).getString("packageName").equals(pkgName)) {
+                    return mWhiteListArray.getJSONObject(i).getString("bannerName");
+                }
+            } catch (JSONException ex) {
+                Log.w(TAG, ex.getMessage());
+            }
+        }
+
+        return "";
+    }
+
+    private JSONArray parseXml(XmlResourceParser xmlParser) {
+        if (xmlParser == null) return null;
+
+        JSONObject jsonObj = null;
+        ArrayList<JSONObject> widgetConfigs = new ArrayList<>();
+        try {
+            int type = xmlParser.getEventType();
+            while (type != XmlResourceParser.END_DOCUMENT) {
+                switch (type) {
+                    case XmlResourceParser.START_TAG:
+                        if (xmlParser.getName().equals("app")) {
+                            jsonObj = new JSONObject();
+                            for (int i = 0; i < xmlParser.getAttributeCount(); i++) {
+                                jsonObj.put(xmlParser.getAttributeName(i),
+                                        xmlParser.getAttributeValue(i));
+                            }
+                            break;
+                        }
+                        break;
+                    case XmlResourceParser.END_TAG:
+                        if (xmlParser.getName().equals("app") && jsonObj != null) {
+                            widgetConfigs.add(jsonObj);
+                            break;
+                        }
+                        break;
+                    default:
+                        break;
+                }
+                type = xmlParser.next();
+            }
+        } catch (IOException | JSONException | XmlPullParserException e) {
+            e.printStackTrace();
+        }
+
+        return new JSONArray(widgetConfigs);
+    }
+}
diff --git a/core/java/com/nvidia/profilemanager/NvAppProfileSettingId.java b/core/java/com/nvidia/profilemanager/NvAppProfileSettingId.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c78f2b8dc576cff59c6a1744b00a2ef3639566f
--- /dev/null
+++ b/core/java/com/nvidia/profilemanager/NvAppProfileSettingId.java
@@ -0,0 +1,93 @@
+package com.nvidia.profilemanager;
+
+public class NvAppProfileSettingId {
+    public static int RESOVERRIDE_SCALE_FACTOR = 5;
+    public static int STEREO_PERF_WIDTH = 7;
+    public static int RESOVERRIDE_PERF_WIDTH = 8;
+    public static int FORCE_HW_UI = 9;
+    public static int CORE_BIAS = 17;
+    public static int CPU_FREQ_BIAS = 18;
+    public static int GPU_CORE_CAP = 19;
+    public static int SCALING_MIN_FREQ = 20;
+    public static int GPU_SCALING = 21;
+    public static int PBC_PWR_LIMIT = 22;
+    public static int FAN_PWM_CAP = 23;
+    public static int VOLT_TEMP_MODE = 24;
+    public static int FRAME_RATE_LIMIT = 26;
+    public static int DISABLE_APM = 29;
+    public static int EDP_MODE = 30;
+    public static int GPU_MODE = 35;
+    public static int STYLUS_FINGER_ONLY_MODE = 40;
+    public static int STEREO_PERF_SCALE_FACTOR = 43;
+    public static int DISABLE_BUFFER_AGE = 47;
+    public static int SYSTEM_POWER_MODE = 48;
+    public static int CUSTOM_PROFILE_BLACKLIST = 51;
+    public static int BLOCK_NETWORK_ACCESS = 53;
+    public static int MAX_CPU_CORES = 58;
+    public static int AGGRESSIVE_PRISM_ENABLE = 59;
+    public static int BLOCK_ON_NETWORK = 60;
+    public static int MAX_CPU_FREQ_PCT = 61;
+    public static int DEPTH_COMPRESSION = 62;
+    public static int OGL_THREADCONTROL = 63;
+    public static int OGL_SKIP_ENABLED_UNSET_ARRAY = 64;
+    public static int CMU_GTM_MAPPING_LUT = 65;
+    public static int OGL_CLEAR_METERING = 66;
+    public static int KILL_PROCESS_BELOW_ADJ = 67;
+    public static int EGL_REPORT_ES1_CONFIG_ONLY = 69;
+    public static int VIDEO_IQ = 70;
+    public static int CAMERA_MEMORY = 71;
+    public static int PERF_FP = 72;
+    public static int MIN_CPU_CORES = 73;
+    public static int PROMOTE_SURFACE_TO_32BIT = 74;
+    public static int AFFINITY_DAEMON_ENABLE = 75;
+    public static int CUSTOM_PROFILE_SYSTEM_WHITELIST = 76;
+    public static int FORCEONCPU = 77;
+    public static int KEY_DEVICE_ID_HASH = 78;
+    public static int GSYNC_WHITELIST = 79;
+    public static int GSYNC_BLACKLIST = 80;
+    public static int TOUCH_MODE = 81;
+    public static int DISPLAY_UPSCALE_HEIGHT = 82;
+    public static int DISPLAY_UPSCALE_WIDTH = 83;
+    public static int OGL_APP_RUNTIME_VERTEX_ATTRIB_SOURCING = 84;
+    public static int MAXWELL_TILEDCACHE = 85;
+    public static int OGL_HIDE_EXTENSIONS_STRING = 86;
+    public static int NVIDIA_WEBVIEW = 87;
+    public static int OGL_HIDE_EXTENSIONS = 88;
+    public static int HDD_DIALOG_FREQ = 89;
+    public static int HDD_DIALOG_TEXT = 90;
+    public static int HDD_DIALOG_THRESHOLD = 91;
+    public static int HDD_DIALOG_ENABLE = 92;
+    public static int TCP_DIVISOR = 93;
+    public static int BBC_APPS = 94;
+    public static int HDD_STATS_ENABLE = 95;
+    public static int HDD_DIALOG_REMIND_ME_LATER_FREQ = 96;
+    public static int HDD_STATS_FREQ = 97;
+    public static int HDD_DIALOG_STR_THRESHOLD = 98;
+    public static int OGL_VERSION_OVERRIDE = 99;
+    public static int OGL_ES_VERSION_OVERRIDE = 100;
+    public static int MULTI_CHANNEL_SWITCH_MODE = 101;
+    public static int VIDEO_FRC_ENABLE = 102;
+    public static int VIDEO_SECURE_DECODE = 103;
+    public static int VIDEO_TS_FILTERING = 104;
+    public static int NVIDIA_VIDEO_CERTIFICATION_ENABLED = 105;
+    public static int OGL_SHADER_PORTABILITY_WARNINGS = 106;
+    public static int OGL_THREADCONTROL2 = 107;
+    public static int OGL_EXTRA_CGC_OPTION = 108;
+    public static int DISABLE_APP = 109;
+    public static int SET_REGION_LIST = 110;
+    public static int PINNING_ENABLE = 111;
+    public static int PINNING_ORDER = 112;
+    public static int GPU_MODESET_ENABLE = 113;
+    public static int AVS_DELAY_ENABLE = 114;
+    public static int BLACKLIST_USB_30 = 115;
+    public static int DRM_DIALOG_ENABLE = 116;
+    public static int FILTER_EGLCONFIGS = 117;
+    public static int SHIELD_LOGGING = 118;
+    public static int APP_AUDIO_SWITCH_TO_STEREO = 119;
+    public static int WHITELIST_CUSTOMIZE_BANNER = 120;
+    public static int NV_MAPPER_GAME_LIST = 121;
+    public static int NV_MULTI_CAPTURE_MOD = 122;
+    public static int MEDIA_ENABLE_MSD_HAL = 123;
+    public static int DEEPISP_DISABLED = 124;
+    public static int OGL_GPFIFO_SIZE_ENTRIES = 125;
+}
diff --git a/core/java/com/nvidia/profilemanager/ProfileTypeId.java b/core/java/com/nvidia/profilemanager/ProfileTypeId.java
new file mode 100644
index 0000000000000000000000000000000000000000..db85b0fc577f15a2af8fbe1f2003d163e43d474f
--- /dev/null
+++ b/core/java/com/nvidia/profilemanager/ProfileTypeId.java
@@ -0,0 +1,11 @@
+package com.nvidia.profilemanager;
+
+public class ProfileTypeId {
+    public static int LAST_RESERVED_TYPE = 9999;
+
+    public static int DEFAULT = 0;
+    public static int OEM_OVERRIDE = 1;
+    public static int DEV_OVERRIDE = 2;
+    public static int USER = 10000;
+    public static int OPTIMIZED = 10001;
+}
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3f53f246a8a4acf580620141b6110f192eb8ad25..a0be9081e428ff3242e5d9bbc4437e541937d528 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1617,6 +1617,7 @@
   <java-symbol type="xml" name="default_zen_mode_config" />
   <java-symbol type="xml" name="sms_7bit_translation_table" />
   <java-symbol type="xml" name="color_extraction" />
+  <java-symbol type="xml" name="tv_launcher_app_white_list" />
 
   <java-symbol type="raw" name="color_fade_vert" />
   <java-symbol type="raw" name="color_fade_frag" />
diff --git a/core/res/res/xml/tv_launcher_app_white_list.xml b/core/res/res/xml/tv_launcher_app_white_list.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e2b226327686cfe3e8a7b4464b66bdf486dffefb
--- /dev/null
+++ b/core/res/res/xml/tv_launcher_app_white_list.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<black-list-apps>
+</black-list-apps>
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1fc23578b46dd6696fe4a8021dac08f5ced27bc2..42e9aa9005df9b2c73ae6b4306e064c991d96e3c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -412,6 +412,8 @@ import com.android.server.utils.WatchedSparseIntArray;
 import com.android.server.utils.Watcher;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
+import com.nvidia.NvAppProfileService;
+
 import dalvik.system.CloseGuard;
 import dalvik.system.VMRuntime;
 
@@ -1455,6 +1457,8 @@ public class PackageManagerService extends IPackageManager.Stub
 
     final PackageInstallerService mInstallerService;
 
+    private NvAppProfileService mAppProfileService;
+
     final ArtManagerService mArtManagerService;
 
     final PackageDexOptimizer mPackageDexOptimizer;
@@ -7420,6 +7424,13 @@ public class PackageManagerService extends IPackageManager.Stub
             public boolean hasFeature(String feature) {
                 return PackageManagerService.this.hasSystemFeature(feature, 0);
             }
+
+            public NvAppProfileService getAppProfileService() {
+                if (mAppProfileService == null) {
+                    mAppProfileService = new NvAppProfileService(mContext);
+                }
+                return mAppProfileService;
+            }
         };
 
         // CHECKSTYLE:ON IndentationCheck
diff --git a/test-mock/src/android/test/mock/MockPackageManager.java b/test-mock/src/android/test/mock/MockPackageManager.java
index 5f95bc124de677494d38b8e833b1a8703cf59848..1f6aedfb8d52dbe1dbc28fb2f611f41324ad530f 100644
--- a/test-mock/src/android/test/mock/MockPackageManager.java
+++ b/test-mock/src/android/test/mock/MockPackageManager.java
@@ -55,6 +55,8 @@ import android.os.PersistableBundle;
 import android.os.UserHandle;
 import android.os.storage.VolumeInfo;
 
+import com.nvidia.NvAppProfileService;
+
 import java.util.List;
 import java.util.Set;
 
@@ -178,6 +180,12 @@ public class MockPackageManager extends PackageManager {
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public NvAppProfileService getAppProfileService() {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public ApplicationInfo getApplicationInfo(String packageName, int flags)
             throws NameNotFoundException {