2016-11-15 23:52:49 +00:00
/ *
2017-06-12 22:30:41 +00:00
* Copyright ( C ) 2013 - 2017 microG Project Team
2016-11-15 23:52:49 +00:00
*
* 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 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.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 ;
}
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 . getColumnIndex ( FIELD_PACKAGE_NAME ) ) ;
lastError = cursor . getString ( cursor . getColumnIndex ( FIELD_LAST_ERROR ) ) ;
lastMessageTimestamp = cursor . getLong ( cursor . getColumnIndex ( FIELD_LAST_MESSAGE_TIMESTAMP ) ) ;
totalMessageCount = cursor . getLong ( cursor . getColumnIndex ( FIELD_TOTAL_MESSAGE_COUNT ) ) ;
totalMessageBytes = cursor . getLong ( cursor . getColumnIndex ( FIELD_TOTAL_MESSAGE_BYTES ) ) ;
allowRegister = cursor . getLong ( cursor . getColumnIndex ( FIELD_ALLOW_REGISTER ) ) = = 1 ;
wakeForDelivery = cursor . getLong ( cursor . getColumnIndex ( 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 . getColumnIndex ( FIELD_PACKAGE_NAME ) ) ;
signature = cursor . getString ( cursor . getColumnIndex ( FIELD_SIGNATURE ) ) ;
timestamp = cursor . getLong ( cursor . getColumnIndex ( FIELD_TIMESTAMP ) ) ;
registerId = cursor . getString ( cursor . getColumnIndex ( 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 " ) ;
}
}