implement auto-freeze on lock

This commit is contained in:
Peter Cai 2018-09-26 16:45:16 +08:00
parent 0b55c8932b
commit 519fc0de85
No known key found for this signature in database
GPG key ID: 71F5FB4E4F3FD54F
10 changed files with 124 additions and 3 deletions

View file

@ -111,6 +111,9 @@
<!-- A hack service to ensure every ShelterService is killed when App is removed -->
<!-- from recent tasks -->
<service android:name=".services.KillerService" />
<!-- Service to freeze apps on screen lock -->
<service android:name=".services.FreezeService" />
</application>
</manifest>

View file

@ -0,0 +1,70 @@
package net.typeblog.shelter.services;
import android.app.Service;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import net.typeblog.shelter.receivers.ShelterDeviceAdminReceiver;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.Nullable;
// This service simply registers a screen-off listener that will be called
// when the user locks the screen. When this happens, this service
// will freeze all the apps that the user launched through Unfreeze & Launch
// during the last session.
public class FreezeService extends Service {
// Use a static variable and static methods to store the current list to be frozen
// We don't need to run this service in another process, so the static context should
// be sufficient for this. DummyActivity will use these static methods to add more apps
// to the list
private static List<String> sAppToFreeze = new ArrayList<>();
public static synchronized void registerAppToFreeze(String app) {
if (!sAppToFreeze.contains(app)) {
sAppToFreeze.add(app);
}
}
public static synchronized boolean hasPendingAppToFreeze() {
return sAppToFreeze.size() > 0;
}
// The actual receiver of the screen-off event
private BroadcastReceiver mLockReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (FreezeService.class) {
if (sAppToFreeze.size() > 0) {
DevicePolicyManager dpm = getSystemService(DevicePolicyManager.class);
ComponentName adminComponent = new ComponentName(FreezeService.this, ShelterDeviceAdminReceiver.class);
for (String app : sAppToFreeze) {
dpm.setApplicationHidden(adminComponent, app, true);
}
sAppToFreeze.clear();
}
unregisterReceiver(this);
stopSelf();
}
}
};
@Override
public void onCreate() {
super.onCreate();
// This is the only thing that we do
registerReceiver(mLockReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

View file

@ -58,8 +58,8 @@ public class ShelterService extends Service {
((ShelterApplication) getApplication()).unbindShelterService();
if (kill) {
// Just kill the entire process if this signal is received
if (kill && !(mIsProfileOwner && FreezeService.hasPendingAppToFreeze())) {
// Just kill the entire process if this signal is received and the process has nothing to do
System.exit(0);
}
}).start();

View file

@ -21,6 +21,7 @@ import androidx.annotation.Nullable;
import net.typeblog.shelter.R;
import net.typeblog.shelter.ShelterApplication;
import net.typeblog.shelter.receivers.ShelterDeviceAdminReceiver;
import net.typeblog.shelter.services.FreezeService;
import net.typeblog.shelter.services.IAppInstallCallback;
import net.typeblog.shelter.services.IFileShuttleService;
import net.typeblog.shelter.services.IFileShuttleServiceCallback;
@ -312,7 +313,12 @@ public class DummyActivity extends Activity {
// Forward it to work profile
Intent intent = new Intent(UNFREEZE_AND_LAUNCH);
Utility.transferIntentToProfile(this, intent);
intent.putExtra("packageName", getIntent().getStringExtra("packageName"));
String packageName = getIntent().getStringExtra("packageName");
intent.putExtra("packageName", packageName);
intent.putExtra("shouldFreeze",
SettingsManager.getInstance().getAutoFreezeServiceEnabled() &&
LocalStorageManager.getInstance()
.stringListContains(LocalStorageManager.PREF_AUTO_FREEZE_LIST_WORK_PROFILE, packageName));
startActivity(intent);
finish();
return;
@ -329,6 +335,10 @@ public class DummyActivity extends Activity {
Intent launchIntent = getPackageManager().getLaunchIntentForPackage(packageName);
if (launchIntent != null) {
if (getIntent().getBooleanExtra("shouldFreeze", false)) {
FreezeService.registerAppToFreeze(packageName);
startService(new Intent(this, FreezeService.class));
}
startActivity(launchIntent);
}

View file

@ -17,10 +17,12 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Prefer
private static final String SETTINGS_SOURCE_CODE = "settings_source_code";
private static final String SETTINGS_BUG_REPORT = "settings_bug_report";
private static final String SETTINGS_CROSS_PROFILE_FILE_CHOOSER = "settings_cross_profile_file_chooser";
private static final String SETTINGS_AUTO_FREEZE_SERVICE = "settings_auto_freeze_service";
private SettingsManager mManager = SettingsManager.getInstance();
private CheckBoxPreference mPrefCrossProfileFileChooser = null;
private CheckBoxPreference mPrefAutoFreezeService = null;
@Override
public void onCreatePreferences(Bundle bundle, String s) {
@ -45,6 +47,11 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Prefer
mPrefCrossProfileFileChooser = (CheckBoxPreference) findPreference(SETTINGS_CROSS_PROFILE_FILE_CHOOSER);
mPrefCrossProfileFileChooser.setChecked(mManager.getCrossProfileFileChooserEnabled());
mPrefCrossProfileFileChooser.setOnPreferenceChangeListener(this);
// === Services ===
mPrefAutoFreezeService = (CheckBoxPreference) findPreference(SETTINGS_AUTO_FREEZE_SERVICE);
mPrefAutoFreezeService.setChecked(mManager.getAutoFreezeServiceEnabled());
mPrefAutoFreezeService.setOnPreferenceChangeListener(this);
}
private boolean openSummaryUrl(Preference pref) {
@ -59,6 +66,9 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Prefer
if (preference == mPrefCrossProfileFileChooser) {
mManager.setCrossProfileFileChooserEnabled((boolean) newState);
return true;
} else if (preference == mPrefAutoFreezeService) {
mManager.setAutoFreezeServiceEnabled((boolean) newState);
return true;
} else {
return false;
}

View file

@ -14,6 +14,7 @@ public class LocalStorageManager {
public static final String PREF_AUTO_FREEZE_LIST_WORK_PROFILE = "auto_freeze_list_work_profile";
public static final String PREF_CROSS_PROFILE_FILE_CHOOSER = "cross_profile_file_chooser";
public static final String PREF_AUTH_KEY = "auth_key";
public static final String PREF_AUTO_FREEZE_SERVICE = "auto_freeze_service";
private static final String LIST_DIVIDER = ",";

View file

@ -59,4 +59,15 @@ public class SettingsManager {
public boolean getCrossProfileFileChooserEnabled() {
return mStorage.getBoolean(LocalStorageManager.PREF_CROSS_PROFILE_FILE_CHOOSER);
}
// Set the enabled state of the auto freeze service
// This does NOT need to be synchronized nor applied across profile
public void setAutoFreezeServiceEnabled(boolean enabled) {
mStorage.setBoolean(LocalStorageManager.PREF_AUTO_FREEZE_SERVICE, enabled);
}
// Get the enabled state of the auto freeze service
public boolean getAutoFreezeServiceEnabled() {
return mStorage.getBoolean(LocalStorageManager.PREF_AUTO_FREEZE_SERVICE);
}
}

View file

@ -37,6 +37,9 @@
<string name="settings_interaction">交互</string>
<string name="settings_cross_profile_file_chooser">文件穿梭</string>
<string name="settings_cross_profile_file_chooser_desc">打开以后,您将可以且仅可以从系统的 Documents UI (启动器上的名称为 文件 或 下载) 或支持 Documents UI 的 APP 中 浏览 / 查看 / 选择 / 复制 Shelter 内的文件到主用户,反之亦然。这不会影响对文件系统的隔离。即使是支持 Documents UI 的 App 也只能临时获取您选择的文件的访问权限。</string>
<string name="settings_services">服务</string>
<string name="settings_auto_freeze_service">自动冻结服务</string>
<string name="settings_auto_freeze_service_desc">在您锁屏时,自动冻结您通过 \"解冻并运行\" 启动的应用</string>
<string name="settings_about">关于</string>
<string name="settings_version">版本</string>
<string name="settings_source_code">源代码</string>

View file

@ -39,6 +39,9 @@
<string name="settings_interaction">Interaction</string>
<string name="settings_cross_profile_file_chooser">File Shuttle</string>
<string name="settings_cross_profile_file_chooser_desc">When enabled, you\'ll be able to browse / view / pick / copy files in Shelter from main profile and vice-versa, ONLY through Documents UI (named Files or Documents on your launcher) or apps with Documents UI support (they only gain temporary access to files you choose in Documents UI), while still pertaining the filesystem isolation.</string>
<string name="settings_services">Services</string>
<string name="settings_auto_freeze_service">Auto Freeze Service</string>
<string name="settings_auto_freeze_service_desc">Automatically freeze apps you launched from \"Unfreeze &amp; Launch Shortcut\" when you lock your screen.</string>
<string name="settings_about">About</string>
<string name="settings_version">Version</string>
<string name="settings_source_code">Source Code</string>

View file

@ -12,6 +12,16 @@
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:title="@string/settings_services">
<androidx.preference.CheckBoxPreference
android:key="settings_auto_freeze_service"
android:title="@string/settings_auto_freeze_service"
android:summary="@string/settings_auto_freeze_service_desc" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:title="@string/settings_about">