/* * Copyright (C) 2018 The Android Open Source Project * * 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.android.settings.fuelgauge.batterytip; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; import androidx.annotation.IntDef; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Database controls the anomaly logging(e.g. packageName, anomalyType and time) */ public class AnomalyDatabaseHelper extends SQLiteOpenHelper { private static final String TAG = "BatteryDatabaseHelper"; private static final String DATABASE_NAME = "battery_settings.db"; private static final int DATABASE_VERSION = 5; @Retention(RetentionPolicy.SOURCE) @IntDef({State.NEW, State.HANDLED, State.AUTO_HANDLED}) public @interface State { int NEW = 0; int HANDLED = 1; int AUTO_HANDLED = 2; } @Retention(RetentionPolicy.SOURCE) @IntDef({ActionType.RESTRICTION}) public @interface ActionType { int RESTRICTION = 0; } public interface Tables { String TABLE_ANOMALY = "anomaly"; String TABLE_ACTION = "action"; } public interface AnomalyColumns { /** * The package name of the anomaly app */ String PACKAGE_NAME = "package_name"; /** * The uid of the anomaly app */ String UID = "uid"; /** * The type of the anomaly app * @see StatsManagerConfig.AnomalyType */ String ANOMALY_TYPE = "anomaly_type"; /** * The state of the anomaly app * @see State */ String ANOMALY_STATE = "anomaly_state"; /** * The time when anomaly happens */ String TIME_STAMP_MS = "time_stamp_ms"; } private static final String CREATE_ANOMALY_TABLE = "CREATE TABLE " + Tables.TABLE_ANOMALY + "(" + AnomalyColumns.UID + " INTEGER NOT NULL, " + AnomalyColumns.PACKAGE_NAME + " TEXT, " + AnomalyColumns.ANOMALY_TYPE + " INTEGER NOT NULL, " + AnomalyColumns.ANOMALY_STATE + " INTEGER NOT NULL, " + AnomalyColumns.TIME_STAMP_MS + " INTEGER NOT NULL, " + " PRIMARY KEY (" + AnomalyColumns.UID + "," + AnomalyColumns.ANOMALY_TYPE + "," + AnomalyColumns.ANOMALY_STATE + "," + AnomalyColumns.TIME_STAMP_MS + ")" + ")"; public interface ActionColumns { /** * The package name of an app been performed an action */ String PACKAGE_NAME = "package_name"; /** * The uid of an app been performed an action */ String UID = "uid"; /** * The type of user action * @see ActionType */ String ACTION_TYPE = "action_type"; /** * The time when action been performed */ String TIME_STAMP_MS = "time_stamp_ms"; } private static final String CREATE_ACTION_TABLE = "CREATE TABLE " + Tables.TABLE_ACTION + "(" + ActionColumns.UID + " INTEGER NOT NULL, " + ActionColumns.PACKAGE_NAME + " TEXT, " + ActionColumns.ACTION_TYPE + " INTEGER NOT NULL, " + ActionColumns.TIME_STAMP_MS + " INTEGER NOT NULL, " + " PRIMARY KEY (" + ActionColumns.ACTION_TYPE + "," + ActionColumns.UID + "," + ActionColumns.PACKAGE_NAME + ")" + ")"; private static AnomalyDatabaseHelper sSingleton; public static synchronized AnomalyDatabaseHelper getInstance(Context context) { if (sSingleton == null) { sSingleton = new AnomalyDatabaseHelper(context.getApplicationContext()); } return sSingleton; } private AnomalyDatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { bootstrapDB(db); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion < DATABASE_VERSION) { Log.w(TAG, "Detected schema version '" + oldVersion + "'. " + "Index needs to be rebuilt for schema version '" + newVersion + "'."); // We need to drop the tables and recreate them reconstruct(db); } } @Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(TAG, "Detected schema version '" + oldVersion + "'. " + "Index needs to be rebuilt for schema version '" + newVersion + "'."); // We need to drop the tables and recreate them reconstruct(db); } public void reconstruct(SQLiteDatabase db) { dropTables(db); bootstrapDB(db); } private void bootstrapDB(SQLiteDatabase db) { db.execSQL(CREATE_ANOMALY_TABLE); db.execSQL(CREATE_ACTION_TABLE); Log.i(TAG, "Bootstrapped database"); } private void dropTables(SQLiteDatabase db) { db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_ANOMALY); db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_ACTION); } }