RK Android5.1 MTK SchedulePowerOnOff
一.初解定时开关机
1.1.packages\apps\SchedulePowerOnOff\src\com\mediatek\schpwronoff\AlarmProvider.java
/* Copyright Statement: * * This software/firmware and related documentation ("MediaTek Software") are * protected under relevant copyright laws. The information contained herein * is confidential and proprietary to MediaTek Inc. and/or its licensors. * Without the prior written permission of MediaTek inc. and/or its licensors, * any reproduction, modification, use or disclosure of MediaTek Software, * and information contained herein, in whole or in part, shall be strictly prohibited. */ /* MediaTek Inc. (C) 2010. All rights reserved. * * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. * * The following software/firmware and/or related documentation ("MediaTek Software") * have been modified by MediaTek Inc. All revisions are subject to any receiver's * applicable license agreements with MediaTek Inc. */ package com.mediatek.schpwronoff; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDiskIOException; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.text.TextUtils; import android.util.Log; public class AlarmProvider extends ContentProvider { private static final String TAG = "AlarmProvider"; private SQLiteOpenHelper mOpenHelper; private static final int SCHPWRS = 1; private static final int SCHPWRS_ID = 2; private static final UriMatcher URLMATCHER = new UriMatcher(UriMatcher.NO_MATCH); static { URLMATCHER.addURI("com.mediatek.schpwronoff", "schpwr", SCHPWRS); URLMATCHER.addURI("com.mediatek.schpwronoff", "schpwr/#", SCHPWRS_ID); } private static class DatabaseHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "schpwrs.db"; private static final int DATABASE_VERSION = 5; public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE schpwrs (" + "_id INTEGER PRIMARY KEY," + "hour INTEGER, " + "minutes INTEGER, " + "daysofweek INTEGER, " + "alarmtime INTEGER, " + "enabled INTEGER, " + "vibrate INTEGER, " + "message TEXT, " + "alert TEXT);"); // insert default alarms String insertMe = "INSERT INTO schpwrs " + "(hour, minutes, daysofweek, alarmtime, enabled, vibrate, message, alert) " + "VALUES "; db.execSQL(insertMe + "(9, 0, 127, 0, 0, 1, '', '');"); db.execSQL(insertMe + "(23, 00, 127, 0, 0, 1, '', '');"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) { Log.d("@M_" + TAG, "Upgrading schpwrs database from version " + oldVersion + " to " + currentVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS schpwrs"); onCreate(db); } } /** * dummy constructor */ public AlarmProvider() { super(); } @Override public boolean onCreate() { mOpenHelper = new DatabaseHelper(getContext()); return true; } @Override public Cursor query(Uri url, String[] projectionIn, String selection, String[] selectionArgs, String sort) { SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); // Generate the body of the query int match = URLMATCHER.match(url); switch (match) { case SCHPWRS: qb.setTables("schpwrs"); break; case SCHPWRS_ID: qb.setTables("schpwrs"); qb.appendWhere("_id="); qb.appendWhere(url.getPathSegments().get(1)); break; default: throw new IllegalArgumentException("Unknown URL " + url); } SQLiteDatabase db = mOpenHelper.getReadableDatabase(); Cursor ret = qb.query(db, projectionIn, selection, selectionArgs, null, null, sort); if (ret == null) { Log.e("@M_" + TAG, "Alarms.query: failed"); } else { ret.setNotificationUri(getContext().getContentResolver(), url); } return ret; } @Override public String getType(Uri url) { int match = URLMATCHER.match(url); switch (match) { case SCHPWRS: return "vnd.android.cursor.dir/schpwrs"; case SCHPWRS_ID: return "vnd.android.cursor.item/schpwrs"; default: throw new IllegalArgumentException("Unknown URL"); } } @Override public int update(Uri url, ContentValues values, String where, String[] whereArgs) { int count; long rowId = 0; int match = URLMATCHER.match(url); try { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); switch (match) { case SCHPWRS_ID: String segment = url.getPathSegments().get(1); rowId = Long.parseLong(segment); count = db.update("schpwrs", values, "_id=" + rowId, null); break; default: throw new UnsupportedOperationException("Cannot update URL: " + url); } Log.d("@M_" + TAG, "*** notifyChange() rowId: " + rowId + " url " + url); getContext().getContentResolver().notifyChange(url, null); return count; } catch (SQLiteDiskIOException e) { Log.e("@M_" + TAG, e.toString()); return 0; } } @Override public Uri insert(Uri url, ContentValues initialValues) { Log.d("@M_" + TAG, "---------->>> alarm provider"); if (URLMATCHER.match(url) != SCHPWRS) { throw new IllegalArgumentException("Cannot insert into URL: " + url); } ContentValues values; if (initialValues == null) { values = new ContentValues(); } else { values = new ContentValues(initialValues); } if (!values.containsKey(Alarm.Columns.HOUR)) { values.put(Alarm.Columns.HOUR, 0); } if (!values.containsKey(Alarm.Columns.MINUTES)) { values.put(Alarm.Columns.MINUTES, 0); } if (!values.containsKey(Alarm.Columns.DAYS_OF_WEEK)) { values.put(Alarm.Columns.DAYS_OF_WEEK, 0); } if (!values.containsKey(Alarm.Columns.ALARM_TIME)) { values.put(Alarm.Columns.ALARM_TIME, 0); } if (!values.containsKey(Alarm.Columns.ENABLED)) { values.put(Alarm.Columns.ENABLED, 0); } if (!values.containsKey(Alarm.Columns.VIBRATE)) { values.put(Alarm.Columns.VIBRATE, 1); } if (!values.containsKey(Alarm.Columns.MESSAGE)) { values.put(Alarm.Columns.MESSAGE, ""); } if (!values.containsKey(Alarm.Columns.ALERT)) { values.put(Alarm.Columns.ALERT, ""); } SQLiteDatabase db = mOpenHelper.getWritableDatabase(); long rowId = db.insert("schpwrs", Alarm.Columns.MESSAGE, values); if (rowId < 0) { throw new SQLException("Failed to insert row into " + url); } Log.d("@M_" + TAG, "Added alarm rowId = " + rowId); Uri newUrl = ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, rowId); getContext().getContentResolver().notifyChange(newUrl, null); return newUrl; } @Override public int delete(Uri url, String where, String[] whereArgs) { Log.d("@M_" + TAG, "---->> delete alarm provider"); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int count; String whr; switch (URLMATCHER.match(url)) { case SCHPWRS: count = db.delete("schpwrs", where, whereArgs); break; case SCHPWRS_ID: String segment = url.getPathSegments().get(1); if (TextUtils.isEmpty(where)) { whr = "_id=" + segment; } else { whr = "_id=" + segment + " AND (" + where + ")"; } count = db.delete("schpwrs", whr, whereArgs); break; default: throw new IllegalArgumentException("Cannot delete from URL: " + url); } getContext().getContentResolver().notifyChange(url, null); return count; } }
建表 插入默认定时开关机时间 查询、修改、插入、删除
private static class DatabaseHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "schpwrs.db"; private static final int DATABASE_VERSION = 5; public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE schpwrs (" + "_id INTEGER PRIMARY KEY," + "hour INTEGER, " + "minutes INTEGER, " + "daysofweek INTEGER, " + "alarmtime INTEGER, " + "enabled INTEGER, " + "vibrate INTEGER, " + "message TEXT, " + "alert TEXT);"); // insert default alarms String insertMe = "INSERT INTO schpwrs " + "(hour, minutes, daysofweek, alarmtime, enabled, vibrate, message, alert) " + "VALUES "; db.execSQL(insertMe + "(9, 0, 127, 0, 0, 1, '', '');"); db.execSQL(insertMe + "(23, 00, 127, 0, 0, 1, '', '');"); } //在数据库的版本发生变化时会被调用 一般在软件升级时才需改变版本号 而数据库的版本是由程序员控制的 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) { Log.d("@M_" + TAG, "Upgrading schpwrs database from version " + oldVersion + " to " + currentVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS schpwrs"); onCreate(db); } }
1.2.packages\apps\SchedulePowerOnOff\src\com\mediatek\schpwronoff\Alarm.java 数据库的工具类
public static class Columns implements BaseColumns { /** * The content:// style URL for this table */ public static final Uri CONTENT_URI = Uri.parse("content://com.mediatek.schpwronoff/schpwr");
Alarm 的构造方法 游标来取值
/** * Alarm object constructor * @param c Cursor */ public Alarm(Cursor c) { mId = c.getInt(Columns.ALARM_ID_INDEX); mEnabled = c.getInt(Columns.ALARM_ENABLED_INDEX) == 1; mHour = c.getInt(Columns.ALARM_HOUR_INDEX); mMinutes = c.getInt(Columns.ALARM_MINUTES_INDEX); mDaysOfWeek = new DaysOfWeek(c.getInt(Columns.ALARM_DAYS_OF_WEEK_INDEX)); mTime = c.getLong(Columns.ALARM_TIME_INDEX); mVibrate = c.getInt(Columns.ALARM_VIBRATE_INDEX) == 1; mLabel = c.getString(Columns.ALARM_MESSAGE_INDEX); String alertString = c.getString(Columns.ALARM_ALERT_INDEX); if (Alarms.ALARM_ALERT_SILENT.equals(alertString)) { Log.d("@M_" + TAG, "Alarm is marked as silent"); mSilent = true; } else { if (alertString != null && alertString.length() != 0) { mAlert = Uri.parse(alertString); } // If the database alert is null or it failed to parse, use the // default alert. if (mAlert == null) { mAlert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM); } } }
1.3. packages\apps\SchedulePowerOnOff\src\com\mediatek\schpwronoff\Alarms.java
设置定时开关机时间
public static void setAlarm(Context context, int id, boolean enabled, int hour, int minutes, Alarm.DaysOfWeek daysOfWeek, boolean vibrate, String message, String alert) { final int initSize = 8; ContentValues values = new ContentValues(initSize); ContentResolver resolver = context.getContentResolver(); // Set the alarm_time value if this alarm does not repeat. This will be // used later to disable expired alarms. long time = 0; if (!daysOfWeek.isRepeatSet()) { time = calculateAlarm(hour, minutes, daysOfWeek).getTimeInMillis(); } Log.d("@M_" + TAG, "** setAlarm * idx " + id + " hour " + hour + " minutes " + minutes + " enabled " + enabled + " time " + time); values.put(Alarm.Columns.ENABLED, enabled ? 1 : 0); values.put(Alarm.Columns.HOUR, hour); values.put(Alarm.Columns.MINUTES, minutes); values.put(Alarm.Columns.ALARM_TIME, time); values.put(Alarm.Columns.DAYS_OF_WEEK, daysOfWeek.getCoded()); values.put(Alarm.Columns.VIBRATE, vibrate); values.put(Alarm.Columns.MESSAGE, message); values.put(Alarm.Columns.ALERT, alert); resolver.update(ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, id), values, null, null); if (id == 1) { // power on setNextAlertPowerOn(context); } else if (id == 2) { // power off setNextAlertPowerOff(context); } }
setNextAlertPowerOff -> enableAlert(context, alarm, alarm.mTime);
am.setExact(AlarmManager.RTC_WAKEUP, atTimeInMillis, sender);
private static void enableAlert(Context context, final Alarm alarm, final long atTimeInMillis) { if (alarm == null) { return; } AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Log.d("@M_" + TAG, "** enableAlertPowerOff id " + alarm.mId + " atTime " + atTimeInMillis); Intent intent = new Intent(context, com.mediatek.schpwronoff.SchPwrOffReceiver.class); Parcel out = Parcel.obtain(); alarm.writeToParcel(out, 0); out.setDataPosition(0); intent.putExtra(ALARM_RAW_DATA, out.marshall()); PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); am.setExact(AlarmManager.RTC_WAKEUP, atTimeInMillis, sender); Calendar c = Calendar.getInstance(); c.setTime(new java.util.Date(atTimeInMillis)); String poweroffdate=getFormatedDateTime("yy-MM-dd HH:mm:ss",atTimeInMillis); Log.d("@M_" + TAG, "Alarms.enableAlertPowerOff(): setAlert id " + alarm.mId + " poweroffdate " + poweroffdate); } private static void disableAlert(Context context) { Intent intent = new Intent(context, com.mediatek.schpwronoff.SchPwrOffReceiver.class); AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); am.cancel(sender); Log.d("@M_" + TAG, "Alarms.disableAlertPowerOff(): disableForPowerOff"); }
1.4.packages\apps\SchedulePowerOnOff\src\com\mediatek\schpwronoff\AlarmInitReceiver.java
调起AlarmReceiverService
public class AlarmInitReceiver extends BroadcastReceiver { private static final String TAG = "AlarmInitReceiver"; @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.d("@M_" + TAG, "AlarmInitReceiver" + action); if (context.getContentResolver() == null) { Log.e("@M_" + TAG, "AlarmInitReceiver: FAILURE unable to get content resolver. Alarms inactive."); return; } AlarmReceiverService.processBroadcastIntent(context, intent); } }
收到开机广播 开始设置下次定时开关机时间
@Override protected void onHandleIntent(Intent intent) { final String action = intent.getAction(); if (!ACTION_BROADCAST.equals(action)) { return; } if(!isFromPowerOn()) { return; } final Intent broadcastIntent = intent .getParcelableExtra(Intent.EXTRA_INTENT); final String broadcastAction = broadcastIntent.getAction(); if (Intent.ACTION_BOOT_COMPLETED.equals(broadcastAction)) { // ALPS00448092. Log.i("@M_" + TAG, "action= " + broadcastAction); boolean b = copyDbFileFromDataPath(); Log.w("@M_" + TAG, "copy db file result " + b); Alarms.saveSnoozeAlert(this, -1, -1); Alarms.disableExpiredAlarms(this); Alarms.setNextAlert(this); } else { //Alarms.setNextAlert(this); } }