Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4cc8827e authored by Aaron Kling's avatar Aaron Kling Committed by Paul Keith
Browse files

Add nvidia profile manager

This implements and API for apps to interface with NvCPL and by
extension the PowerHAL.

Reverse engineered from the Shield Experience 8.2.0 update then cleaned
up to match Android standards.

Change-Id: I774ac62c8867151f21712cfeee25f96a591415ad
parent 41730287
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -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 {
+7 −0
Original line number Diff line number Diff line
@@ -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;
@@ -4678,6 +4680,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.
     *
+7 −0
Original line number Diff line number Diff line
@@ -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);
        }
+246 −0
Original line number Diff line number Diff line
/*
 * 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");
    }
}
+96 −0
Original line number Diff line number Diff line
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);
        }
    }
}
Loading