Fix a bug where Aegis would forcibly pop up after unlocking the device

This commit is contained in:
Alexander Bakker 2019-05-12 17:12:09 +02:00 committed by Michael Schättgen
parent 98c166a6b2
commit 57e3574693
3 changed files with 72 additions and 25 deletions

View file

@ -13,19 +13,23 @@ import android.os.Build;
import com.beemdevelopment.aegis.db.DatabaseManager; import com.beemdevelopment.aegis.db.DatabaseManager;
import com.beemdevelopment.aegis.ui.MainActivity; import com.beemdevelopment.aegis.ui.MainActivity;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
public class AegisApplication extends Application { public class AegisApplication extends Application {
private DatabaseManager _manager; private DatabaseManager _manager;
private Preferences _prefs; private Preferences _prefs;
private List<LockListener> _lockListeners;
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
_manager = new DatabaseManager(this); _manager = new DatabaseManager(this);
_prefs = new Preferences(this); _prefs = new Preferences(this);
_lockListeners = new ArrayList<>();
// listen for SCREEN_OFF events // listen for SCREEN_OFF events
ScreenOffReceiver receiver = new ScreenOffReceiver(); ScreenOffReceiver receiver = new ScreenOffReceiver();
@ -44,6 +48,25 @@ public class AegisApplication extends Application {
return _prefs; return _prefs;
} }
public boolean isAutoLockEnabled() {
return _prefs.isAutoLockEnabled() && _manager.isLoaded() && _manager.isEncryptionEnabled() && !_manager.isLocked();
}
public void registerLockListener(LockListener listener) {
_lockListeners.add(listener);
}
public void unregisterLockListener(LockListener listener) {
_lockListeners.remove(listener);
}
public void lock() {
_manager.lock();
for (LockListener listener : _lockListeners) {
listener.onLocked();
}
}
@RequiresApi(api = Build.VERSION_CODES.N_MR1) @RequiresApi(api = Build.VERSION_CODES.N_MR1)
private void initAppShortcuts() { private void initAppShortcuts() {
ShortcutManager shortcutManager = getSystemService(ShortcutManager.class); ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
@ -65,19 +88,16 @@ public class AegisApplication extends Application {
shortcutManager.setDynamicShortcuts(Collections.singletonList(shortcut)); shortcutManager.setDynamicShortcuts(Collections.singletonList(shortcut));
} }
public boolean isAutoLockEnabled() {
return _prefs.isAutoLockEnabled() && _manager.isLoaded() && _manager.isEncryptionEnabled() && !_manager.isLocked();
}
private class ScreenOffReceiver extends BroadcastReceiver { private class ScreenOffReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (isAutoLockEnabled()) { if (isAutoLockEnabled()) {
_manager.lock(); lock();
Intent newIntent = new Intent(getApplicationContext(), MainActivity.class);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(newIntent);
} }
} }
} }
public interface LockListener {
void onLocked();
}
} }

View file

@ -13,9 +13,10 @@ import com.beemdevelopment.aegis.Preferences;
import com.beemdevelopment.aegis.R; import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.Theme; import com.beemdevelopment.aegis.Theme;
import androidx.annotation.CallSuper;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
public abstract class AegisActivity extends AppCompatActivity { public abstract class AegisActivity extends AppCompatActivity implements AegisApplication.LockListener {
private AegisApplication _app; private AegisApplication _app;
@Override @Override
@ -27,11 +28,10 @@ public abstract class AegisActivity extends AppCompatActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// if the app was killed, relaunch MainActivity and close everything else // if the app was killed, relaunch MainActivity and close everything else
if (!(this instanceof MainActivity) && !(this instanceof AuthActivity) && _app.getDatabaseManager().isLocked()) { if (savedInstanceState != null && isOrphan()) {
Intent intent = new Intent(this, MainActivity.class); Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent); startActivity(intent);
finish();
return; return;
} }
@ -42,6 +42,24 @@ public abstract class AegisActivity extends AppCompatActivity {
// apply a dirty hack to make progress bars work even if animations are disabled // apply a dirty hack to make progress bars work even if animations are disabled
setGlobalAnimationDurationScale(); setGlobalAnimationDurationScale();
// register a callback to listen for lock events
_app.registerLockListener(this);
}
@Override
protected void onDestroy() {
_app.unregisterLockListener(this);
super.onDestroy();
}
@CallSuper
@Override
public void onLocked() {
if (isOrphan()) {
setResult(RESULT_CANCELED, null);
finish();
}
} }
protected AegisApplication getApp() { protected AegisApplication getApp() {
@ -66,6 +84,14 @@ public abstract class AegisActivity extends AppCompatActivity {
} }
} }
/**
* Reports whether this Activity instance has become an orphan. This can happen if
* the vault was locked by an external trigger while the Activity was still open.
*/
private boolean isOrphan() {
return !(this instanceof MainActivity) && _app.getDatabaseManager().isLocked();
}
private void setGlobalAnimationDurationScale() { private void setGlobalAnimationDurationScale() {
float durationScale = Settings.Global.getFloat(getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 0); float durationScale = Settings.Global.getFloat(getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 0);
if (durationScale != 1) { if (durationScale != 1) {

View file

@ -147,6 +147,11 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
return; return;
} }
// don't process any activity results if the vault is locked
if (requestCode != CODE_DECRYPT && _db.isLocked()) {
return;
}
switch (requestCode) { switch (requestCode) {
case CODE_SCAN: case CODE_SCAN:
onScanResult(resultCode, data); onScanResult(resultCode, data);
@ -371,10 +376,6 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
intent.removeExtra("action"); intent.removeExtra("action");
} }
public void startActivityForResult(Intent intent, int requestCode) {
super.startActivityForResult(intent, requestCode);
}
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
@ -411,7 +412,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
@Override @Override
public void onBackPressed() { public void onBackPressed() {
if (_app.isAutoLockEnabled()) { if (_app.isAutoLockEnabled()) {
lockDatabase(); _app.lock();
} }
super.onBackPressed(); super.onBackPressed();
@ -481,7 +482,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
startActivityForResult(intent, CODE_PREFERENCES); startActivityForResult(intent, CODE_PREFERENCES);
return true; return true;
case R.id.action_lock: case R.id.action_lock:
lockDatabase(); _app.lock();
startAuthActivity(); startAuthActivity();
return true; return true;
default: default:
@ -525,14 +526,6 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
} }
} }
private void lockDatabase() {
if (_loaded) {
_entryListView.clearEntries();
_db.lock();
_loaded = false;
}
}
private void unlockDatabase(DatabaseFileCredentials creds) { private void unlockDatabase(DatabaseFileCredentials creds) {
if (_loaded) { if (_loaded) {
return; return;
@ -570,6 +563,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
private void startAuthActivity() { private void startAuthActivity() {
Intent intent = new Intent(this, AuthActivity.class); Intent intent = new Intent(this, AuthActivity.class);
intent.putExtra("slots", _db.getFileHeader().getSlots()); intent.putExtra("slots", _db.getFileHeader().getSlots());
intent.putExtra("requiresUnlock", false);
startActivityForResult(intent, CODE_DECRYPT); startActivityForResult(intent, CODE_DECRYPT);
} }
@ -613,4 +607,11 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
public void onScroll(int dx, int dy) { public void onScroll(int dx, int dy) {
_fabScrollHelper.onScroll(dx, dy); _fabScrollHelper.onScroll(dx, dy);
} }
@Override
public void onLocked() {
_entryListView.clearEntries();
_loaded = false;
super.onLocked();
}
} }