VancedMicroG/play-services-core/src/main/java/org/microg/gms/gcm/GcmDatabase.java

317 lines
13 KiB
Java

/*
* SPDX-FileCopyrightText: 2016, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.gcm;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class GcmDatabase extends SQLiteOpenHelper {
private static final String TAG = GcmDatabase.class.getSimpleName();
public static final String DB_NAME = "gcmstatus";
private static int DB_VERSION = 1;
private static final String CREATE_TABLE_APPS = "CREATE TABLE apps (" +
"package_name TEXT," +
"last_error TEXT DEFAULT ''," +
"last_message_timestamp INTEGER," +
"total_message_count INTEGER," +
"total_message_bytes INTEGER," +
"allow_register INTEGER DEFAULT 1," +
"wake_for_delivery INTEGER DEFAULT 1," +
"PRIMARY KEY (package_name));";
private static final String TABLE_APPS = "apps";
private static final String FIELD_PACKAGE_NAME = "package_name";
private static final String FIELD_LAST_ERROR = "last_error";
private static final String FIELD_LAST_MESSAGE_TIMESTAMP = "last_message_timestamp";
private static final String FIELD_TOTAL_MESSAGE_COUNT = "total_message_count";
private static final String FIELD_TOTAL_MESSAGE_BYTES = "total_message_bytes";
private static final String FIELD_ALLOW_REGISTER = "allow_register";
private static final String FIELD_WAKE_FOR_DELIVERY = "wake_for_delivery";
private static final String CREATE_TABLE_REGISTRATIONS = "CREATE TABLE registrations (" +
"package_name TEXT," +
"signature TEXT," +
"timestamp INTEGER," +
"register_id TEXT," +
"PRIMARY KEY (package_name, signature));";
private static final String TABLE_REGISTRATIONS = "registrations";
private static final String FIELD_SIGNATURE = "signature";
private static final String FIELD_TIMESTAMP = "timestamp";
private static final String FIELD_REGISTER_ID = "register_id";
private Context context;
public GcmDatabase(Context context) {
super(context, DB_NAME, null, DB_VERSION);
this.context = context;
if (Build.VERSION.SDK_INT >= 16) {
this.setWriteAheadLoggingEnabled(true);
}
}
public static class App {
public final String packageName;
public final String lastError;
public final long lastMessageTimestamp;
public final long totalMessageCount;
public final long totalMessageBytes;
public final boolean allowRegister;
public final boolean wakeForDelivery;
private App(Cursor cursor) {
packageName = cursor.getString(cursor.getColumnIndexOrThrow(FIELD_PACKAGE_NAME));
lastError = cursor.getString(cursor.getColumnIndexOrThrow(FIELD_LAST_ERROR));
lastMessageTimestamp = cursor.getLong(cursor.getColumnIndexOrThrow(FIELD_LAST_MESSAGE_TIMESTAMP));
totalMessageCount = cursor.getLong(cursor.getColumnIndexOrThrow(FIELD_TOTAL_MESSAGE_COUNT));
totalMessageBytes = cursor.getLong(cursor.getColumnIndexOrThrow(FIELD_TOTAL_MESSAGE_BYTES));
allowRegister = cursor.getLong(cursor.getColumnIndexOrThrow(FIELD_ALLOW_REGISTER)) == 1;
wakeForDelivery = cursor.getLong(cursor.getColumnIndexOrThrow(FIELD_WAKE_FOR_DELIVERY)) == 1;
}
public boolean hasError() {
return !TextUtils.isEmpty(lastError);
}
}
public static class Registration {
public final String packageName;
public final String signature;
public final long timestamp;
public final String registerId;
public Registration(Cursor cursor) {
packageName = cursor.getString(cursor.getColumnIndexOrThrow(FIELD_PACKAGE_NAME));
signature = cursor.getString(cursor.getColumnIndexOrThrow(FIELD_SIGNATURE));
timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(FIELD_TIMESTAMP));
registerId = cursor.getString(cursor.getColumnIndexOrThrow(FIELD_REGISTER_ID));
}
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_APPS);
db.execSQL(CREATE_TABLE_REGISTRATIONS);
importLegacyData(db);
}
public synchronized List<App> getAppList() {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(TABLE_APPS, null, null, null, null, null, null);
if (cursor != null) {
List<App> result = new ArrayList<>();
while (cursor.moveToNext()) {
result.add(new App(cursor));
}
cursor.close();
return result;
}
return Collections.emptyList();
}
public synchronized List<Registration> getRegistrationList() {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(TABLE_REGISTRATIONS, null, null, null, null, null, null);
if (cursor != null) {
List<Registration> result = new ArrayList<>();
while (cursor.moveToNext()) {
result.add(new Registration(cursor));
}
cursor.close();
return result;
}
return Collections.emptyList();
}
public synchronized List<Registration> getRegistrationsByApp(String packageName) {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(TABLE_REGISTRATIONS, null, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName}, null, null, null);
if (cursor != null) {
List<Registration> result = new ArrayList<>();
while (cursor.moveToNext()) {
result.add(new Registration(cursor));
}
cursor.close();
return result;
}
return Collections.emptyList();
}
public synchronized void setAppAllowRegister(String packageName, boolean allowRegister) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(FIELD_ALLOW_REGISTER, allowRegister ? 1 : 0);
db.update(TABLE_APPS, cv, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
}
public synchronized void setAppWakeForDelivery(String packageName, boolean wakeForDelivery) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(FIELD_WAKE_FOR_DELIVERY, wakeForDelivery ? 1 : 0);
db.update(TABLE_APPS, cv, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
}
public synchronized void removeApp(String packageName) {
SQLiteDatabase db = getWritableDatabase();
db.delete(TABLE_REGISTRATIONS, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
db.delete(TABLE_APPS, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
}
public synchronized void noteAppRegistrationError(String packageName, String error) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(FIELD_LAST_ERROR, error);
db.update(TABLE_APPS, cv, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
}
public synchronized void noteAppKnown(String packageName, boolean allowRegister) {
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
App app = getApp(db, packageName);
ContentValues cv = new ContentValues();
cv.put(FIELD_ALLOW_REGISTER, allowRegister);
if (app == null) {
cv.put(FIELD_PACKAGE_NAME, packageName);
db.insert(TABLE_APPS, null, cv);
} else {
db.update(TABLE_APPS, cv, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
}
db.setTransactionSuccessful();
db.endTransaction();
}
public synchronized void noteAppMessage(String packageName, int numBytes) {
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
App app = getApp(db, packageName);
ContentValues cv = new ContentValues();
cv.put(FIELD_LAST_MESSAGE_TIMESTAMP, System.currentTimeMillis());
if (app == null) {
cv.put(FIELD_PACKAGE_NAME, packageName);
cv.put(FIELD_TOTAL_MESSAGE_COUNT, 1);
cv.put(FIELD_TOTAL_MESSAGE_BYTES, numBytes);
db.insert(TABLE_APPS, null, cv);
} else {
cv.put(FIELD_TOTAL_MESSAGE_COUNT, app.totalMessageCount + 1);
cv.put(FIELD_TOTAL_MESSAGE_BYTES, app.totalMessageBytes + numBytes);
db.update(TABLE_APPS, cv, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
}
db.setTransactionSuccessful();
db.endTransaction();
}
public synchronized void noteAppRegistered(String packageName, String signature, String registrationId) {
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
App app = getApp(db, packageName);
if (app == null) {
ContentValues cv = new ContentValues();
cv.put(FIELD_PACKAGE_NAME, packageName);
db.insert(TABLE_APPS, null, cv);
} else {
ContentValues cv = new ContentValues();
cv.put(FIELD_LAST_ERROR, "");
db.update(TABLE_APPS, cv, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
}
ContentValues cv = new ContentValues();
cv.put(FIELD_PACKAGE_NAME, packageName);
cv.put(FIELD_SIGNATURE, signature);
cv.put(FIELD_REGISTER_ID, registrationId);
cv.put(FIELD_TIMESTAMP, System.currentTimeMillis());
db.insertWithOnConflict(TABLE_REGISTRATIONS, null, cv, SQLiteDatabase.CONFLICT_REPLACE);
db.setTransactionSuccessful();
db.endTransaction();
}
public synchronized void noteAppUnregistered(String packageName, String signature) {
SQLiteDatabase db = getWritableDatabase();
db.delete(TABLE_REGISTRATIONS, FIELD_PACKAGE_NAME + " LIKE ? AND " + FIELD_SIGNATURE + " LIKE ?", new String[]{packageName, signature});
}
public App getApp(String packageName) {
return getApp(getReadableDatabase(), packageName);
}
private App getApp(SQLiteDatabase db, String packageName) {
Cursor cursor = db.query(TABLE_APPS, null, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName}, null, null, null, "1");
if (cursor != null) {
try {
if (cursor.moveToNext()) {
return new App(cursor);
}
} finally {
cursor.close();
}
}
return null;
}
public Registration getRegistration(String packageName, String signature) {
return getRegistration(getReadableDatabase(), packageName, signature);
}
private Registration getRegistration(SQLiteDatabase db, String packageName, String signature) {
Cursor cursor = db.query(TABLE_REGISTRATIONS, null, FIELD_PACKAGE_NAME + " LIKE ? AND " + FIELD_SIGNATURE + " LIKE ?", new String[]{packageName, signature}, null, null, null, "1");
if (cursor != null) {
try {
if (cursor.moveToNext()) {
return new Registration(cursor);
}
} finally {
cursor.close();
}
}
return null;
}
@SuppressWarnings("deprecation")
private void importLegacyData(SQLiteDatabase db) {
db.beginTransaction();
GcmLegacyData legacyData = new GcmLegacyData(context);
for (GcmLegacyData.LegacyAppInfo appInfo : legacyData.getAppsInfo()) {
ContentValues cv = new ContentValues();
cv.put(FIELD_PACKAGE_NAME, appInfo.app);
cv.put(FIELD_TOTAL_MESSAGE_COUNT, legacyData.getAppMessageCount(appInfo.app));
cv.put(FIELD_LAST_ERROR, appInfo.hasUnregistrationError() ? "Unregistration error" : null);
db.insert(TABLE_APPS, null, cv);
cv.clear();
if (appInfo.isRegistered()) {
cv.put(FIELD_PACKAGE_NAME, appInfo.app);
cv.put(FIELD_SIGNATURE, appInfo.appSignature);
cv.put(FIELD_REGISTER_ID, appInfo.registerID);
db.insert(TABLE_REGISTRATIONS, null, cv);
}
}
db.setTransactionSuccessful();
db.endTransaction();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
throw new IllegalStateException("Upgrades not supported");
}
}