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

Commit b231bca2 authored by Kumar Ankit's avatar Kumar Ankit Committed by Android (Google) Code Review
Browse files

Merge "[TelephonyAnalytics_Implementation] Utils to support TelephonyAnalytics" into main

parents d1913783 3eb205b4
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.internal.telephony.analytics;

import android.provider.BaseColumns;

import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

/**
 * Defines the tables classes which are present in the Telephony Analytics Database, private
 * constructor to prevent instantiation.
 */
public final class TelephonyAnalyticsDatabase {
    private TelephonyAnalyticsDatabase() {}

    public static final DateTimeFormatter DATE_FORMAT =
            DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.systemDefault());

    /**
     * CallAnalyticsTable class defines the columns in the CallTable Implements the BaseColumns
     * class.
     */
    public static final class CallAnalyticsTable implements BaseColumns {
        public static final String TABLE_NAME = "CallDataLogs";
        public static final String LOG_DATE = "LogDate";
        public static final String CALL_STATUS = "CallStatus";
        public static final String CALL_TYPE = "CallType";
        public static final String RAT = "RAT";
        public static final String SLOT_ID = "SlotID";
        public static final String FAILURE_REASON = "FailureReason";
        public static final String RELEASE_VERSION = "ReleaseVersion";
        public static final String COUNT = "Count";
    }

    /**
     * SmsMmsAnalyticsTable class defines the columns in the SmsMmsTable Implements the BaseColumns
     * class.
     */
    public static final class SmsMmsAnalyticsTable implements BaseColumns {
        public static final String TABLE_NAME = "SmsMmsDataLogs";
        public static final String LOG_DATE = "LogDate";
        public static final String SMS_MMS_STATUS = "SmsMmsStatus";
        public static final String SMS_MMS_TYPE = "SmsMmsType";
        public static final String SLOT_ID = "SlotID";
        public static final String RAT = "RAT";
        public static final String FAILURE_REASON = "FailureReason";
        public static final String RELEASE_VERSION = "ReleaseVersion";
        public static final String COUNT = "Count";
    }

    /**
     * ServiceStateAnalyticsTable class defines the columns in the ServiceStateTable Implements the
     * BaseColumns class.
     */
    public static final class ServiceStateAnalyticsTable implements BaseColumns {
        public static final String TABLE_NAME = "ServiceStateLogs";
        public static final String LOG_DATE = "LogDate";
        public static final String TIME_DURATION = "TimeDuration";
        public static final String SLOT_ID = "SlotID";
        public static final String RAT = "RAT";
        public static final String DEVICE_STATUS = "DeviceStatus";
        public static final String RELEASE_VERSION = "ReleaseVersion";
    }
}
+30 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.internal.telephony.analytics;

import java.util.ArrayList;
/**
 * Interface for Telephony Provider Classes
 */
public interface TelephonyAnalyticsProvider {
    /**
     * Aggregates all information from the db.
     * Used when the bugreport is to be pulled.
     * @return All the aggregated information in a ArrayList.
     */
    ArrayList<String> aggregate();
}
+187 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.internal.telephony.analytics;

import static com.android.internal.telephony.analytics.TelephonyAnalyticsDatabase.DATE_FORMAT;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.android.internal.annotations.VisibleForTesting;
import com.android.telephony.Rlog;

import java.util.Calendar;

/**
 * Singleton Utility class to support TelephonyAnalytics Extends SQLiteOpenHelper class. Supports db
 * related operations which includes creating tables,insertion,updation,deletion. Supports some
 * generic functionality like getting the Cursor resulting from a query.
 */
public class TelephonyAnalyticsUtil extends SQLiteOpenHelper {
    private static TelephonyAnalyticsUtil sTelephonyAnalyticsUtil;
    private static final String DATABASE_NAME = "telephony_analytics.db";
    private static final int DATABASE_VERSION = 10;
    private static final String TAG = TelephonyAnalyticsUtil.class.getSimpleName();
    private static final int MAX_ENTRIES_LIMIT = 1000;
    private static final int CUTOFF_MONTHS = 2;

    private TelephonyAnalyticsUtil(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    /**
     * Get the instance of the TelephonyAnalyticsUtil class. Instantiates the TelephonyAnalyticsUtil
     * object sTelephonyAnalyticsUtil only once.
     *
     * @return Returns the TelephonyAnalyticsUtil object sTelephonyAnalyticsUtil.
     */
    public static synchronized TelephonyAnalyticsUtil getInstance(Context context) {
        if (sTelephonyAnalyticsUtil == null) {
            sTelephonyAnalyticsUtil = new TelephonyAnalyticsUtil(context);
        }
        return sTelephonyAnalyticsUtil;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {}

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}

    /**
     * Uses Util class functionality to create CallTable in db
     *
     * @param createTableQuery : CallTable Schema
     */
    @VisibleForTesting
    public synchronized void createTable(String createTableQuery) {
        try {
            SQLiteDatabase db = getWritableDatabase();
            db.execSQL(createTableQuery);
        } catch (Exception e) {
            Rlog.e(TAG, "Error during table creation : " + e);
        }
    }

    /** Utility function that performs insertion on the given database table */
    @VisibleForTesting
    public synchronized void insert(String tableName, ContentValues values) {
        try {
            SQLiteDatabase db = getWritableDatabase();
            db.insert(tableName, null, values);
        } catch (SQLException e) {
            Rlog.e(TAG, "error occurred during insertion");
        }
    }

    /** Utility function that performs update query on the given database table */
    @VisibleForTesting
    public synchronized int update(
            String table, ContentValues values, String whereClause, String[] whereArgs) {
        int rowsAffected = -1;
        try {
            SQLiteDatabase db = getWritableDatabase();
            rowsAffected = db.update(table, values, whereClause, whereArgs);

        } catch (SQLException e) {
            Rlog.e(TAG, "Error during update.");
        }
        return rowsAffected;
    }

    /**
     * @Return the cursor object obtained from running a query based on given parameters.
     */
    @VisibleForTesting
    public synchronized Cursor getCursor(
            String tableName,
            String[] columns,
            String selection,
            String[] selectionArgs,
            String groupBy,
            String having,
            String orderBy,
            String limit) {

        Cursor cursor = null;
        try {
            SQLiteDatabase db = getReadableDatabase();
            cursor =
                    db.query(
                            tableName,
                            columns,
                            selection,
                            selectionArgs,
                            groupBy,
                            having,
                            orderBy,
                            limit);
        } catch (SQLException e) {
            Rlog.e(TAG, "Error during querying for getCursor()" + e);
        }
        return cursor;
    }

    /** Returns the count stored in the cursor obtained from query execution. */
    @VisibleForTesting
    public synchronized long getCountFromCursor(Cursor cursor) {
        long count = 0;
        if (cursor != null && cursor.moveToFirst()) {
            count = cursor.getInt(0);
        }
        return count;
    }

    /** Deletes Old Data and Overflow data in the db. */
    @VisibleForTesting
    public void deleteOverflowAndOldData(
            String tableName, String overflowWhereClause, String oldDataWhereClause) {
        deleteOverFlowData(tableName, overflowWhereClause);
        deleteOldData(tableName, oldDataWhereClause);
    }

    protected void deleteOverFlowData(String tableName, String whereClause) {
        String[] whereArgs = {Integer.toString(MAX_ENTRIES_LIMIT)};
        delete(tableName, whereClause, whereArgs);
    }

    protected void deleteOldData(String tableName, String whereClause) {
        String[] whereArgs = {getCutoffDate()};
        delete(tableName, whereClause, whereArgs);
    }

    /** Utility function that performs deletion on the database table */
    @VisibleForTesting
    public synchronized void delete(String tableName, String whereClause, String[] whereArgs) {
        try {
            SQLiteDatabase db = getWritableDatabase();
            db.delete(tableName, whereClause, whereArgs);
        } catch (SQLException e) {
            Rlog.e(TAG, "Sqlite Operation Error during deletion of Overflow data " + e);
        }
    }

    private String getCutoffDate() {
        Calendar cutoffDate = Calendar.getInstance();
        cutoffDate.add(Calendar.MONTH, -1 * CUTOFF_MONTHS);
        return DATE_FORMAT.format(cutoffDate.toInstant());
    }
}