android 增加定时开关机

定时关机

增加一个系统服务,定时关机相关接口

	private void setPowerOff(Intent intent) {
		boolean enable = intent.getBooleanExtra(VAL_POWEROFF,false);
		Intent inten;
		if(enable) {
			inten = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
			inten.putExtra(Intent.EXTRA_KEY_CONFIRM,false);
			inten.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			mContext.startActivity(inten);
		} else {
		    inten = new Intent(Intent.ACTION_REBOOT);
		    inten.putExtra("nowait", 1);
		    inten.putExtra("interval", 1);
		    inten.putExtra("window", 0);
		    mContext.sendBroadcast(inten);
		}
	}

定时关机app启动调用如下

    public void setTimePowerOff(long time) {
        Log.d(TAG,"time:" + time);
        AlarmManager am = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(ACTION);
        intent.putExtra(CMD_KEY,CMD_ID_POWEROFF);
        intent.putExtra(VAL_POWEROFF,true);//这里这个intent最后广播会调用上面的系统服务setPowerOff
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
                intent, PendingIntent.FLAG_CANCEL_CURRENT);
        am.set(AlarmManager.RTC_WAKEUP, time, pendingIntent);
    }
      long time =  System.currentTimeMillis() + 10 * 1000;//10秒后关机
      setTimePowerOff(time);

定时关机,实际基本没什么困难。

定时开机

设备外接的rtc芯片为pcf8563,要实现硬件开机,硬件上需要将pcf8563的INT脚接到POWER KEY上,具体硬件具体接法,实际流程是达到设置的时间后pcf8563会将INT脚接低,此时INT接接在POWER KEY上就相当于常按开机键进行开机,开机启动后在清除pcf8563的状态使INT脚变高.
只是提供给特定软件使用,所以增加的不是系统接口,直接使用JNI进行设置定时开机
pcf8563驱动修改

diff --git a/lichee/linux-3.4/drivers/rtc/rtc-pcf8563.c b/lichee/linux-3.4/drivers/rtc/rtc-pcf8563.c
index cd3b4bb..ed4ae78 100755
--- a/lichee/linux-3.4/drivers/rtc/rtc-pcf8563.c
+++ b/lichee/linux-3.4/drivers/rtc/rtc-pcf8563.c
@@ -24,6 +24,9 @@

 #define PCF8563_REG_ST1		0x00 /* status */
 #define PCF8563_REG_ST2		0x01
+#define PCF8563_BIT_AIE		(1 << 1)
+#define PCF8563_BIT_AF		(1 << 3)
+#define PCF8563_BITS_ST2_N	(7 << 5)

 #define PCF8563_REG_SC		0x02 /* datetime */
 #define PCF8563_REG_MN		0x03
@@ -183,10 +186,130 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	return pcf8563_set_datetime(to_i2c_client(dev), tm);
 }

-static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+static int pcf8563_read_block_data(struct i2c_client *client, unsigned char reg,
+				   unsigned char length, unsigned char *buf)
 {
+	struct i2c_msg msgs[] = {
+		{/* setup read ptr */
+			.addr = client->addr,
+			.len = 1,
+			.buf = &reg,
+		},
+		{
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = length,
+			.buf = buf
+		},
+	};
+
+	if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
+		dev_err(&client->dev, "%s: read error\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int pcf8563_write_block_data(struct i2c_client *client,
+				   unsigned char reg, unsigned char length,
+				   unsigned char *buf)
+{
+	int i, err;
+
+	for (i = 0; i < length; i++) {
+		unsigned char data[2] = { reg + i, buf[i] };
+
+		err = i2c_master_send(client, data, sizeof(data));
+		if (err != sizeof(data)) {
+			dev_err(&client->dev,
+				"%s: err=%d addr=%02x, data=%02x\n",
+				__func__, err, data[0], data[1]);
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+static int pcf8563_set_alarm_mode(struct i2c_client *client, bool on)
+{
+	unsigned char buf;
+	int err;
+
+	err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf);
+	if (err < 0)
+		return err;
+
+	if (on)
+		buf |= PCF8563_BIT_AIE;
+	else
+		buf &= ~PCF8563_BIT_AIE;
+
+	buf &= ~(PCF8563_BIT_AF | PCF8563_BITS_ST2_N);
+
+	err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, &buf);
+	if (err < 0) {
+		dev_err(&client->dev, "%s: write error\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int pcf8563_get_alarm_mode(struct i2c_client *client, unsigned char *en,
+				  unsigned char *pen)
+{
+	unsigned char buf;
+	int err;
+
+	err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf);
+	if (err)
+		return err;
+
+	if (en)
+		*en = !!(buf & PCF8563_BIT_AIE);
+	if (pen)
+		*pen = !!(buf & PCF8563_BIT_AF);
+
+	return 0;
+}
+
+static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned char buf[4];
+	int err;
+	/* The alarm has no seconds, round up to nearest minute */
+	/*if (tm->time.tm_sec) {
+		time64_t alarm_time = rtc_tm_to_time64(&tm->time);
+
+		alarm_time += 60 - tm->time.tm_sec;
+		rtc_time64_to_tm(alarm_time, &tm->time);
+	}*/
+
+	dev_dbg(dev, "%s, min=%d hour=%d wday=%d mday=%d "
+		"enabled=%d pending=%d\n", __func__,
+		tm->time.tm_min, tm->time.tm_hour, tm->time.tm_wday,
+		tm->time.tm_mday, tm->enabled, tm->pending);
+
+	buf[0] = bin2bcd(tm->time.tm_min);
+	buf[1] = bin2bcd(tm->time.tm_hour);
+	buf[2] = bin2bcd(tm->time.tm_mday);
+	buf[3] = tm->time.tm_wday & 0x07;
+
+	err = pcf8563_write_block_data(client, PCF8563_REG_AMN, 4, buf);
+	if (err)
+		return err;
+
+	return pcf8563_set_alarm_mode(client, 1);
 }

 static const struct rtc_class_ops pcf8563_rtc_ops = {
@@ -199,7 +322,7 @@ static int pcf8563_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	struct pcf8563 *pcf8563;
-
+	unsigned char alm_pending;
 	int err = 0;

 	dev_dbg(&client->dev, "%s\n", __func__);
@@ -218,7 +341,16 @@ static int pcf8563_probe(struct i2c_client *client,
 	if (!device_can_wakeup(&client->dev)) { //add by hclydao
 		device_init_wakeup(&client->dev, 1);
 	}
-
+
+	err = pcf8563_get_alarm_mode(client, NULL, &alm_pending);//清除状态
+	if (err) {
+		dev_err(&client->dev, "%s: read error\n", __func__);
+		return err;
+	}
+
+	if (alm_pending)
+		pcf8563_set_alarm_mode(client, 0);
+		
 	pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,
 				&client->dev, &pcf8563_rtc_ops, THIS_MODULE);

应用层jni

JNIEXPORT jint JNICALL Java_com_gzease_hwc_Hwc_setRtcPowerOn(JNIEnv * env, jclass obj,jlong millis)
{
    struct timeval tv;
    int ret;
    struct tm tm, *gmtime_res;
    struct rtc_time rtc;
    int fd;
    if (millis <= 0 || millis / 1000LL >= INT_MAX) {
        return -1;
    }
    tv.tv_sec = (time_t) (millis / 1000LL);
    tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
    //LOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
    gmtime_res = gmtime_r(&tv.tv_sec, &tm);
    if (!gmtime_res) {
        LOGE("gmtime_r() failed: %s\n", strerror(errno));
        return -1;
    }
    memset(&rtc, 0, sizeof(rtc));
    rtc.tm_sec = tm.tm_sec;
    rtc.tm_min = tm.tm_min;
    rtc.tm_hour = tm.tm_hour;
    rtc.tm_mday = tm.tm_mday;
    rtc.tm_mon = tm.tm_mon;
    rtc.tm_year = tm.tm_year;
    rtc.tm_wday = tm.tm_wday;
    rtc.tm_yday = tm.tm_yday;
    rtc.tm_isdst = tm.tm_isdst;
    /*LOGD("setAlarm RTC date/time: %d/%d/%d %02d:%02d:%02d\n",
        rtc.tm_mday, rtc.tm_mon + 1, rtc.tm_year + 1900,
        rtc.tm_hour, rtc.tm_min, rtc.tm_sec);*/
    fd = open("/dev/rtc0", O_RDONLY|O_NONBLOCK);
    if (fd == -1) {
        LOGE("setRtc open /dev/rtc0 error");
        return -1;
    }
    ret = ioctl(fd, RTC_ALM_SET, &rtc);
    if (ret == -1) {
        LOGE("ioctl RTC_SET_TIME error");
        close(fd);
        return -1;
    }
    close(fd);
    return 0;
}

java层调用

tim =  System.currentTimeMillis() + 60 * 1000;//60秒后开机 最小单位为分钟 不能小于60秒
setTimePowerOn(tim);

同时需要修改/dev/rtc0权限,定时开机设置使用ioctl(fd, RTC_ALM_SET, &rtc)这个会调用到pcf8563驱动中的pcf8563_rtc_set_alarm,当定时时间到后系统启动在pcf8563 probe函数会使用pcf8563_set_alarm_mode清除状态将INT接高.
如果是在系统里加接口有点麻烦,这里就直接用jni进行设置.
参考:
https://blog.csdn.net/zy_style/article/details/53228509?utm_source=blogxgwz9

======================================
作者:hclydao
http://blog.csdn.net/hclydao
版权没有,但是转载请保留此段声明

=======================================

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Android 10.0中,你可以轻松地设置定时开关功能。这项功能非常实用,可以帮助我们节省电池电量并提供更好的用户体验。 首先,进入“设置”菜单,然后找到“系统”选项,在下拉列表中选择“高级”或类似选项。在这个菜单中,你应该能够找到“定时开关”或类似的功能。 点击进入定时开关功能后,你将看到一个开关选项,允许你启用或禁用该功能。确保开启这个选项以便设置定时开关。 接下来,你可以按照你的需求设置开关的时间。你可以选择每天定时开关,或者在特定的日期和时间进行开关。只需点击相应选项并设置对应的时间值即可。 在设定好时间后,你可以选择是否要打开或关闭声音,以及是否需要提前提醒你关。这样,在设定的时间到达之前,你将会收到一条通知,提醒你关。 一旦你的设定完成,定时开关功能就会生效。你的设备将会在设定的时间自动开关。这对于省电、定时任务和其他场景非常有用。 需要注意的是,定时开关功能可能会受到一些限制,比如,应用程序或系统更新的影响。因此,在使用这个功能时,请确保你的设备处于稳定的状态,并确认没有其他任务正在后台运行。 总之,Android 10.0的定时开关功能是一个非常实用的工具,它可以帮助我们节省电池电量并提供更好的用户体验。无论是为了待时间更长,还是为了设置定时任务,这个功能都可以满足我们的需求。只需要在设置中开启它,并按照自己的需求进行相应设置即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值