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

Commit ca33a1da authored by Karthik Parsha's avatar Karthik Parsha Committed by Giulio Cervera
Browse files

DynamicMemoryManagerService: Add DMM functionality.

Call Power API's to switch unstable memory between Active/Disabled states.
parent c6dd471d
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2007 The Android Open Source Project
 * Copyright (c) 2010-2011, Code Aurora Forum. 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.
@@ -104,4 +105,11 @@ public class Power
    }

    private static native void rebootNative(String reason) throws IOException ;

    /**
     * Activate/DeActivate Unstable Memory block
     *
     * @param on Whether you want Activate(true) or DeActive(False)
     */
    public static native int SetUnstableMemoryState(boolean on);
}
+8 −0
Original line number Diff line number Diff line
/* //device/libs/android_runtime/android_os_Power.cpp
**
** Copyright 2006, The Android Open Source Project
** Copyright (c) 2010-2011, Code Aurora Forum. 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.
@@ -85,6 +86,12 @@ static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason)
    jniThrowIOException(env, errno);
}

static int
SetUnstableMemoryState(JNIEnv *env, jobject clazz, jboolean on)
{
    return set_unstable_memory_state(on);
}

static JNINativeMethod method_table[] = {
    { "acquireWakeLock", "(ILjava/lang/String;)V", (void*)acquireWakeLock },
    { "releaseWakeLock", "(Ljava/lang/String;)V", (void*)releaseWakeLock },
@@ -92,6 +99,7 @@ static JNINativeMethod method_table[] = {
    { "setScreenState", "(Z)I", (void*)setScreenState },
    { "shutdown", "()V", (void*)android_os_Power_shutdown },
    { "rebootNative", "(Ljava/lang/String;)V", (void*)android_os_Power_reboot },
    { "SetUnstableMemoryState",  "(Z)I", (void*)SetUnstableMemoryState},
};

int register_android_os_Power(JNIEnv *env)
+310 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of Code Aurora nor
 *     the names of its contributors may be used to endorse or promote
 *     products derived from this software without specific prior written
 *     permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.android.server;

import android.os.Power;
import android.os.PowerManager;
import android.os.SystemProperties;

import android.app.AlarmManager;
import android.app.PendingIntent;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.text.format.Time;

import java.util.Calendar;
import android.util.Log;

class DynamicMemoryManagerService {
    private final String TAG = "DMM Service";
    private Context mContext;
    private boolean SCREEN_ON = false;
    private boolean DPD_START = false;
    private boolean START_ALARM_SET = false;
    private boolean STOP_ALARM_SET = false;
    private int prevStartHr = 0;
    private int prevStartMin = 0;
    private int prevStopHr = 0;
    private int prevStopMin = 0;
    private enum DMM_MEM_STATE {ACTIVE, DISABLED}
    private DMM_MEM_STATE mState;
    private AlarmManager mStartAlarmManager, mStopAlarmManager;
    private Intent mStartIntent, mStopIntent;
    private PendingIntent mStartPendingIntent, mStopPendingIntent;
    private static final String ACTION_DPD_START =
        "com.android.server.DMMService.action.DPD_START";
    private static final String ACTION_DPD_STOP =
        "com.android.server.DMMService.action.DPD_STOP";

    private final boolean DEBUG = false;

    public DynamicMemoryManagerService(Context context) {
        mContext = context;

        Log.w(TAG, "ro.dev.dmm.dpd.start_address = "
                + SystemProperties.get("ro.dev.dmm.dpd.start_address", "0"));

        if(SystemProperties.get("ro.dev.dmm.dpd.start_address", "0").compareTo("0") != 0) {
                mState = DMM_MEM_STATE.ACTIVE;

                registerForBroadcasts();
                mStartIntent = new Intent(ACTION_DPD_START, null);
                mStopIntent = new Intent(ACTION_DPD_STOP, null);
                mStartPendingIntent = PendingIntent.getBroadcast(mContext, 0, mStartIntent, 0);
                mStopPendingIntent = PendingIntent.getBroadcast(mContext, 0, mStopIntent, 0);
                mStartAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
                mStopAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);

                Log.w(TAG, "DynamicMemoryManager Service Initialized");
        }
        else
            Log.w(TAG, "DynamicMemoryManager Service Disabled.");
    }

    private void registerForBroadcasts() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        intentFilter.addAction(ACTION_DPD_START);
        intentFilter.addAction(ACTION_DPD_STOP);
        mContext.registerReceiver(mReceiver, intentFilter);
    }

    protected void finalize() {
        if (DEBUG) Log.w(TAG, "DynamicMemoryManagerService Finalize");
    }

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if(action.equals(Intent.ACTION_BOOT_COMPLETED)) {
                if (DEBUG) Log.w(TAG, "ACTION_BOOT_COMPLETED");
                manageAlarms();
            }
            else if(action.equals(Intent.ACTION_SCREEN_ON)) {
                if (DEBUG) Log.w(TAG, "ACTION_SCREEN_ON");
                enableUnstableMemory(true);
                SCREEN_ON = true;
            }
            else if(action.equals(Intent.ACTION_SCREEN_OFF)) {
                if (DEBUG) Log.w(TAG, "ACTION_SCREEN_OFF");
                SCREEN_ON = false;

                manageAlarms();
                checkCurrentStatus();
                if (DEBUG) Log.w(TAG, "DPD_START is set to " + DPD_START);

                if(DPD_START)
                    enableUnstableMemory(false);
            }
            else if (action.equals(ACTION_DPD_START)) {
                if (DEBUG) Log.w(TAG, "ACTION_DPD_START");
                DPD_START = true;
                START_ALARM_SET = false;
                if(!SCREEN_ON)
                    enableUnstableMemory(false);
            }
            else if (action.equals(ACTION_DPD_STOP)) {
                if (DEBUG) Log.w(TAG, "ACTION_DPD_STOP");
                DPD_START = false;
                STOP_ALARM_SET = false;
            }
        }
    };

    private boolean manageAlarms() {
        if (DEBUG) Log.w(TAG, "Manage Alarms");

        if(dpdEnabled() == 1) {
            setStartAlarm();
            setStopAlarm();
        }
        else {
            cancelStartAlarm();
            cancelStopAlarm();
            DPD_START = false;
        }
        return true;
    }

    private int dpdEnabled() {
        if (DEBUG) Log.w(TAG, "DPD Enabled: " +
                SystemProperties.getInt("persist.sys.dpd", 1));
        return SystemProperties.getInt("persist.sys.dpd", 1);
    }

    private boolean setStartAlarm() {
        int startHr = SystemProperties.getInt("persist.sys.dpd.start_hr", 20);
        int startMin = SystemProperties.getInt("persist.sys.dpd.start_min", 0);
        long delay_ms = 0;

        if (DEBUG) Log.w(TAG, "DPD_START = " + DPD_START);
        if (DEBUG) Log.w(TAG, "Prev Start: Hr = " + prevStartHr + " Min = " + prevStartMin);
        if (DEBUG) Log.w(TAG, "     Start: Hr = " + startHr + " Min = " + startMin);
        if (DEBUG) Log.w(TAG, "START_ALARM_SET = " + START_ALARM_SET);

        if(startHr != prevStartHr || startMin != prevStartMin || !START_ALARM_SET) {
            prevStartHr = startHr;
            prevStartMin = startMin;
            cancelStartAlarm();
            delay_ms = getDelay(startHr, startMin);
            if (DEBUG) Log.w(TAG, "Set Start Alarm after " + delay_ms + "ms");
            mStartAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
                                            delay_ms,
                                            AlarmManager.INTERVAL_DAY,
                                            mStartPendingIntent);
            START_ALARM_SET = true;
        }
        return true;
    }

    private boolean cancelStartAlarm() {
        if (DEBUG) Log.w(TAG, "Cancel Start Alarm");
        mStartAlarmManager.cancel(mStartPendingIntent);
        START_ALARM_SET = false;
        return true;
    }

    private boolean setStopAlarm() {
        int stopHr = SystemProperties.getInt("persist.sys.dpd.stop_hr", 7);
        int stopMin = SystemProperties.getInt("persist.sys.dpd.stop_min", 0);
        long delay_ms = 0;

        if (DEBUG) Log.w(TAG, "Prev Stop Hr = " + prevStopHr + " Min = " + prevStopMin);
        if (DEBUG) Log.w(TAG, "     Stop Hr = " + stopHr + " Min = " + stopMin);
        if (DEBUG) Log.w(TAG, "STOP_ALARM_SET = " + STOP_ALARM_SET);

        if(stopHr != prevStopHr || stopMin != prevStopMin || !STOP_ALARM_SET) {
            prevStopHr = stopHr;
            prevStopMin = stopMin;
            cancelStopAlarm();
            delay_ms = getDelay(stopHr, stopMin);
            if (DEBUG) Log.w(TAG, "Set Stop Alarm after " + delay_ms + "ms");
            mStopAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
                                           delay_ms,
                                           AlarmManager.INTERVAL_DAY,
                                           mStopPendingIntent);
            STOP_ALARM_SET = true;
        }
        return true;
    }

    private boolean cancelStopAlarm() {
        if (DEBUG) Log.w(TAG, "Cancel Stop Alarm");
        mStopAlarmManager.cancel(mStopPendingIntent);
        STOP_ALARM_SET = false;
        return true;
    }

    private long getDelay(int sHr, int sMin) {
        final Calendar calendar = Calendar.getInstance();
        int dHr = sHr - calendar.get(Calendar.HOUR_OF_DAY);
        int dMin = sMin - calendar.get(Calendar.MINUTE);

        if(dHr < 0)
            dHr = 24 + dHr;
        if(dMin < 0) {
            dMin = 60 + dMin;
            if(dHr > 0)
                dHr = dHr - 1;
            else
                dHr = 24 + dHr - 1;
        }
        if (DEBUG) Log.w(TAG, "Current time " + calendar.get(Calendar.HOUR_OF_DAY) +
                    ":" +calendar.get(Calendar.MINUTE));
        if (DEBUG) Log.w(TAG, "Alarm time " + sHr + ":" + sMin);
        if (DEBUG) Log.w(TAG, "Next Alarm after " + dHr + " hrs and " + dMin + " mins");

        return (((dHr * 60) + dMin) * 60 * 1000) + System.currentTimeMillis();
    }

    private void checkCurrentStatus() {
        final Calendar calendar = Calendar.getInstance();
        int StopDayOfMonth = 0;

        if(dpdEnabled() == 1) {
            StopDayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
            if((prevStartHr > prevStopHr) ||
               ((prevStartHr == prevStopHr) && (prevStartMin > prevStopMin)))
                StopDayOfMonth = StopDayOfMonth + 1;

            Time NowTime = new Time();
            NowTime.setToNow();

            Time StartTime = new Time();
            StartTime.set(calendar.get(Calendar.SECOND),
                            prevStartMin,
                            prevStartHr,
                            calendar.get(Calendar.DAY_OF_MONTH),
                            calendar.get(Calendar.MONTH),
                            calendar.get(Calendar.YEAR));

            Time StopTime = new Time();
            StopTime.set(calendar.get(Calendar.SECOND),
                            prevStopMin,
                            prevStopHr,
                            StopDayOfMonth,
                            calendar.get(Calendar.MONTH),
                            calendar.get(Calendar.YEAR));

            if(NowTime.after(StartTime) && NowTime.before(StopTime))
                DPD_START = true;
            else
                DPD_START = false;
        }
        else {
            DPD_START = false;
        }
    }

    private int enableUnstableMemory(boolean flag) {
        Log.w(TAG, "Enable Unstable Memory : " + flag);
        if (flag) {
            if(mState == DMM_MEM_STATE.DISABLED) {
                if(Power.SetUnstableMemoryState(flag) < 0)
                    Log.e(TAG, "Activating Unstable Memory: Failed !");
                else
                    mState = DMM_MEM_STATE.ACTIVE;
            }
        } else {
            if(mState == DMM_MEM_STATE.ACTIVE) {
                if(Power.SetUnstableMemoryState(flag) < 0)
                    Log.e(TAG, "Disabling Unstable Memory: Failed !");
                else
                        mState = DMM_MEM_STATE.DISABLED;
            }
        }
        return 0;
    }
}
+2 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2006 The Android Open Source Project
 * Copyright (c) 2010-2011, Code Aurora Forum. 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.
@@ -126,6 +127,7 @@ class ServerThread extends Thread {

        LightsService lights = null;
        PowerManagerService power = null;
        DynamicMemoryManagerService dmm = null;
        BatteryService battery = null;
        AlarmManagerService alarm = null;
        NetworkManagementService networkManagement = null;