com.kdb.ledcontrol.LEDManager.java Source code

Java tutorial

Introduction

Here is the source code for com.kdb.ledcontrol.LEDManager.java

Source

/*          Copyright (c) 2015 Krishanu Dutta Bhuyan
 *
 *  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.
 */

package com.kdb.ledcontrol;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Created by KDB on 17/12/2014.
 */
public class LEDManager {
    private static final String pathToLED = "/sys/class/leds/charging/trigger";
    private static final String pathToLEDdir = "/sys/class/leds/";
    private static String devicePathToLED = null;
    private static String devicePathToBrightness = null;
    private static final String getPathToLEDdirAlter = "/sys/class/pm8xx-led/leds";
    private static final String pathToBrightness = "/sys/class/leds/charging/max_brightness";
    private static final String TAG = "LED Control";
    private String SHARED_PREF;
    public SharedPreferences prefs;
    public SharedPreferences.Editor prefsEditor;
    public String cmd;
    public boolean rooted;
    private Context context;
    private Process process;
    private DataOutputStream deviceInput;
    private BufferedReader deviceOutput;
    private String DEVICE_MOTO_X = "ghost";
    private String DEVICE_MOTO_G = "falcon";
    private String DEVICE_MOTO_E = "condor";
    private String DEVICE_NEXUS_6 = "shamu";
    private String DEVICE_MAXX = "obake-maxx";
    private String DEVICE_ULTRA = "obake";
    public final int TRIGGER_BATTERY_CHARGING = 1;
    public final int TRIGGER_BATTERY_FULL = 2;
    public final int TRIGGER_BATTERY_CHARGING_OR_FULL = 3;
    public final int TRIGGER_BATTERY_CHARGING_BLINKING_OR_FULL = 4;
    public final int TRIGGER_USB = 5;
    public final int TRIGGER_BKL_or_MOTOX_ADAPTER = 6;
    public final int TRIGGER_DISK_IO = 7;
    public final int TRIGGER_EXT_IO = 8;
    public final int TRIGGER_BLUETOOTH = 9;
    public final int TRIGGER_TORCH = 10;
    public final int TRIGGER_FLASH = 11;
    public final int TRIGGER_ALWAYS = 12;
    private File chargingDir;
    private File brightnessDir;

    public LEDManager(Context context) {
        this.context = context;
        process = null;
        rooted = true;
        SHARED_PREF = context.getPackageName() + ".prefs";
        prefs = context.getSharedPreferences(SHARED_PREF, 0);
        prefsEditor = prefs.edit();
        //check for root
        try {
            process = Runtime.getRuntime().exec("su");
        } catch (IOException e) {
            e.printStackTrace();
            if (process != null)
                process.destroy();
        }
        //confirming root only if the command "id" has "root"
        if (process != null) {
            deviceOutput = new BufferedReader(new InputStreamReader(process.getInputStream()));
            deviceInput = new DataOutputStream(process.getOutputStream());
            String user = getUser();
            if ((user == null) || (!user.contains("root"))) {
                rooted = false;
            }
        } else {
            rooted = false;
        }
        chargingDir = new File(pathToLEDdir + "charging");
        brightnessDir = new File(pathToBrightness);
        try {
            devicePathToBrightness = brightnessDir.getCanonicalPath();
            devicePathToLED = chargingDir.getCanonicalPath() + "/trigger";
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     *  Returns output from executing command "id"
     */
    private String getUser() {
        if (deviceInput == null || deviceOutput == null) {
            return null;
        }
        String user = null;
        try {
            deviceInput.writeBytes("id\n");
            deviceInput.flush();
            user = deviceOutput.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return user;
    }

    /*
     *  Dynamically sets the value of cmd based on user's choice
     */
    public void setChoice(int Choice) {
        //Don't proceed further if no root access:
        if (!rooted)
            return;
        if (Choice == -2) { //for (int) lastSelected in MainActivity
            cmd = null;
        } else if (Choice == 0) {
            cmd = "none";
        } else if (Choice == R.id.rBtn_Charging) {
            cmd = "battery-charging";
        } else if (Choice == R.id.rBtn_Full) {
            cmd = "battery-full";
        } else if (Choice == R.id.rBtn_Charging_or_full) {
            cmd = "battery-charging-or-full";
        } else if (Choice == R.id.rBtn_Charging_or_full_blink) {
            if (getDevice().equals(DEVICE_MOTO_X)) {
                cmd = "heartbeat";
            } else {
                cmd = "battery-charging-blink-full-solid";
            }
        } else if (Choice == R.id.rBtn_USB) {
            cmd = "usb-online";
        } else if (Choice == R.id.rBtn_Display) {
            if (getDevice().equals(DEVICE_NEXUS_6)) {
                cmd = "backlight";
            } else {
                cmd = "bkl-trigger";
            }
        } else if (Choice == R.id.rBtn_Disk_IO) {
            cmd = "mmc0";
        } else if (Choice == R.id.rBtn_Ext_IO) {
            cmd = "mmc1";
        } else if (Choice == R.id.rBtn_Charging_adapter) {
            if (getDevice().equals(DEVICE_NEXUS_6)) {
                cmd = "dc-online";
            } else {
                cmd = "pm8921-dc-online";
            }
        } else if (Choice == R.id.rBtn_Bluetooth) {
            if (getDevice().equals(DEVICE_NEXUS_6)) {
                cmd = "rkfill0";
            } else
                cmd = "rkfill1";
        } else if (Choice == R.id.rBtn_Always_on) {
            cmd = "default-on";
        } else if (Choice == R.id.rBtn_Cam_flash) {
            cmd = "flash0_trigger";
        } else if (Choice == R.id.rBtn_Torch) {
            cmd = "torch_trigger";
        }
    }

    /*
     * Returns true if a directory called `charging` exists in /sys/class/leds/, to determine if the device is supported
     */
    public boolean isDeviceSupported() {
        return devicePathToLED != null;
    }

    /*
     *  Returns an integer value depending on currently set trigger
     */
    public int checkState() {
        //not aborting if not rooted here, but the directory needs to exist if we wish to 'cat' it
        if (!isDeviceSupported()) {
            return -1;
        }
        String output = null;
        int val = 0;
        try {
            deviceInput.writeBytes("cat " + devicePathToLED + "\n");
            deviceInput.flush();
            output = this.deviceOutput.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (output == null)
            return -1;
        else if (output.contains("[battery-charging]"))
            val = TRIGGER_BATTERY_CHARGING;
        else if (output.contains("[battery-full]"))
            val = TRIGGER_BATTERY_FULL;
        else if (output.contains("[battery-charging-or-full]"))
            val = TRIGGER_BATTERY_CHARGING_OR_FULL;
        else if (output.contains("[battery-charging-blink-full-solid]") || output.contains("[heartbeat]"))
            val = TRIGGER_BATTERY_CHARGING_BLINKING_OR_FULL;
        else if (output.contains("[usb-online]"))
            val = TRIGGER_USB;
        else if (output.contains("[bkl-trigger]") || output.contains("[pm8921-dc-online]")
                || output.contains("[backlight]"))
            val = TRIGGER_BKL_or_MOTOX_ADAPTER;
        else if (output.contains("[mmc0]"))
            val = TRIGGER_DISK_IO;
        else if (output.contains("[mmc1]"))
            val = TRIGGER_EXT_IO;
        else if (output.contains("[rkfill0]") || output.contains("[rkfill1]"))
            val = TRIGGER_BLUETOOTH;
        else if (output.contains("[torch_trigger]"))
            val = TRIGGER_TORCH;
        else if (output.contains("[flash0_trigger]"))
            val = TRIGGER_FLASH;
        else if (output.contains("[default-on]"))
            val = TRIGGER_ALWAYS;
        return val;
    }

    /*
     *  Returns an integer value depending on currently set brightness
     */
    public int checkBrightness() {
        int brightness = 0;
        if (!isDeviceSupported() || devicePathToBrightness == null) {
            return 0;
        }
        try {
            deviceInput.writeBytes("cat " + devicePathToBrightness + "\n");
            deviceInput.flush();
            brightness = Integer.parseInt(deviceOutput.readLine());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return brightness / 25;
    }

    /*
     *  Brings the app to life; the core methods - Apply() and ApplyBrightness()
     */
    public void Apply() {
        //again, stop if root not found:
        if (!rooted || cmd == null || !isDeviceSupported())
            return;
        try {
            deviceInput.writeBytes("echo " + cmd + " > " + devicePathToLED + "\n");
            deviceInput.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        prefsEditor.putString("last_cmd", cmd).apply();
        Log.i(TAG, "Successfully set trigger: " + cmd);
    }

    public void ApplyBrightness(int brightness) {
        if (!rooted || !isDeviceSupported() || devicePathToBrightness == null)
            return;
        if (brightness != 10)
            brightness *= 25;
        else
            brightness = 255;
        try {
            deviceInput.writeBytes("echo " + Integer.toString(brightness) + " > " + devicePathToBrightness + "\n");
            deviceInput.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        prefsEditor.putInt("last_brightness", brightness).apply();
    }

    /*
     *  Returns a String value based on user's device.
     *  Since the app only runs on Moto G, E and X, we need to check if the device is correct
     */
    public String getDevice() {
        if (deviceInput == null || deviceOutput == null)
            return null;
        String device = null;
        String output = Build.DEVICE;
        if (output.contains(DEVICE_MOTO_E))
            device = DEVICE_MOTO_E;
        else if (output.contains(DEVICE_MOTO_G))
            device = DEVICE_MOTO_G;
        else if (output.contains(DEVICE_MOTO_X))
            device = DEVICE_MOTO_X;
        else if (output.contains(DEVICE_NEXUS_6))
            device = DEVICE_NEXUS_6;
        else if (output.contains(DEVICE_MAXX))
            device = DEVICE_MAXX;
        else if (output.contains(DEVICE_ULTRA))
            device = DEVICE_ULTRA;
        return device;
    }

    public void setOnBoot() {
        String cmd = prefs.getString("last_cmd", null);
        int brightness = prefs.getInt("last_brightness", -1);
        if (brightness != -1 && devicePathToBrightness != null) {
            brightness /= 25;
            ApplyBrightness(brightness);
        }
        if (cmd != null && devicePathToLED != null) {
            try {
                deviceInput.writeBytes("echo " + cmd + " > " + devicePathToLED + "\n");
                deviceInput.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (checkState() != -1 && prefs.getBoolean("show_notif", true)) {
            Log.i(TAG, "LED trigger applied on boot");
            Bitmap largeIcon = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
            NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
                    .setSmallIcon(R.drawable.ic_stat_notification).setLargeIcon(largeIcon)
                    .setContentTitle(context.getString(R.string.app_name_full))
                    .setContentText(context.getString(R.string.notification_content));
            Intent resultIntent = new Intent(context, MainActivity.class);
            TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
            stackBuilder.addParentStack(MainActivity.class);
            stackBuilder.addNextIntent(resultIntent);
            PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
            builder.setContentIntent(resultPendingIntent);
            NotificationManager mNotificationManager = (NotificationManager) context
                    .getSystemService(Context.NOTIFICATION_SERVICE);
            mNotificationManager.notify(0, builder.build());
        }
    }
}