From ceb6991339144893c56f45cac943c94f24249f42 Mon Sep 17 00:00:00 2001 From: oasisfeng Date: Fri, 12 Mar 2021 11:42:49 +0800 Subject: [PATCH] UPDATE: Minor tweaks. --- build.gradle | 6 +++--- engine/src/main/AndroidManifest.xml | 5 +++-- .../provisioning/ManualProvisioningReceiver.java | 3 ++- .../island/service/IslandPersistentService.kt | 10 ++++++---- .../oasisfeng/island/controller/IslandAppControl.kt | 3 ++- .../island/settings/AppOpsPermissionsUnlock.kt | 5 ++++- .../oasisfeng/island/settings/IslandNameManager.kt | 3 ++- .../java/com/oasisfeng/island/settings/OpsManager.kt | 2 +- .../oasisfeng/island/shortcut/IslandAppShortcut.kt | 3 ++- mobile/src/main/res/values-zh-rTW/strings.xml | 2 +- mobile/src/main/res/values-zh/strings.xml | 2 +- mobile/src/main/res/values/strings.xml | 2 +- .../oasisfeng/island/api/DelegatedAppOpsManager.java | 2 +- shared/build.gradle | 2 +- shared/src/main/AndroidManifest.xml | 4 ++-- .../oasisfeng/island/InternalContentProviders.java | 11 ----------- .../main/java/com/oasisfeng/island/util/Modules.java | 6 +++--- .../java/com/oasisfeng/island/util/ProfileUser.java | 3 ++- .../main/java/com/oasisfeng/island/util/Users.java | 8 +++++--- .../com/oasisfeng/settings/AppSettingsProvider.kt | 7 +++++-- .../com/oasisfeng/island/watcher/IslandWatcher.kt | 11 +++++------ 21 files changed, 52 insertions(+), 48 deletions(-) delete mode 100644 shared/src/main/java/com/oasisfeng/island/InternalContentProviders.java diff --git a/build.gradle b/build.gradle index 38b4e533b..64c19a6d3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.4.10' + ext.kotlin_version = '1.4.30' ext.kotlin_coroutine_version = '1.3.9' repositories { google() @@ -9,9 +9,9 @@ buildscript { } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:4.1.2' classpath 'com.google.gms:google-services:4.3.4' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.3.0' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/engine/src/main/AndroidManifest.xml b/engine/src/main/AndroidManifest.xml index c538bfb58..68b23b597 100644 --- a/engine/src/main/AndroidManifest.xml +++ b/engine/src/main/AndroidManifest.xml @@ -106,7 +106,7 @@ - + @@ -136,7 +136,8 @@ - + diff --git a/engine/src/main/java/com/oasisfeng/island/provisioning/ManualProvisioningReceiver.java b/engine/src/main/java/com/oasisfeng/island/provisioning/ManualProvisioningReceiver.java index 1cd04c580..67c004606 100644 --- a/engine/src/main/java/com/oasisfeng/island/provisioning/ManualProvisioningReceiver.java +++ b/engine/src/main/java/com/oasisfeng/island/provisioning/ManualProvisioningReceiver.java @@ -15,7 +15,8 @@ /** * Receiver for starting post-provisioning procedure for manual provisioning. - * The enabled state of this receiver also serves as an indication of pending manual provisioning. + * + * The enabled state of this receiver in managed profile also serves as an indication of pending manual provisioning. * * Created by Oasis on 2017/4/8. */ diff --git a/engine/src/main/java/com/oasisfeng/island/service/IslandPersistentService.kt b/engine/src/main/java/com/oasisfeng/island/service/IslandPersistentService.kt index 75a59ae93..c37f42df8 100644 --- a/engine/src/main/java/com/oasisfeng/island/service/IslandPersistentService.kt +++ b/engine/src/main/java/com/oasisfeng/island/service/IslandPersistentService.kt @@ -68,15 +68,17 @@ import com.oasisfeng.island.util.toId if (try { pm.getApplicationInfo(pkg, 0).enabled } catch (e: PackageManager.NameNotFoundException) { false }) bindPersistentServices(pkg) else unbindPersistentServices(pkg) - } else components.forEach { - val info = try { pm.getServiceInfo(ComponentName(pkg, it), MATCH_DISABLED_COMPONENTS or MATCH_UNINSTALLED_PACKAGES) } + } else components.forEach { className -> + val component = ComponentName(pkg, className) + val info = try { pm.getServiceInfo(component, MATCH_DISABLED_COMPONENTS or MATCH_UNINSTALLED_PACKAGES) } catch (e: PackageManager.NameNotFoundException) { return@forEach } // Non-service component - if (info.isEnabled && ! info.applicationInfo.hidden) bindPersistentService(info) + if (info.isEnabled && ! info.applicationInfo.hidden) { + if (mConnections.none { it.mComponent == component }) bindPersistentService(info) } else unbindPersistentService(info.getComponentName()) } }} private fun unbindPersistentService(component: ComponentName) { - mConnections.removeIf { if (it.mComponent == component) { unbindService(it); true } else false } + mConnections.removeIf { (it.mComponent == component).also { matched -> if (matched) { unbindService(it) }}} } private fun unbindPersistentServices(pkg: String) { diff --git a/mobile/src/main/java/com/oasisfeng/island/controller/IslandAppControl.kt b/mobile/src/main/java/com/oasisfeng/island/controller/IslandAppControl.kt index 44805903b..7c5d0dc36 100644 --- a/mobile/src/main/java/com/oasisfeng/island/controller/IslandAppControl.kt +++ b/mobile/src/main/java/com/oasisfeng/island/controller/IslandAppControl.kt @@ -12,6 +12,7 @@ import android.widget.Toast import com.oasisfeng.android.app.Activities import com.oasisfeng.android.content.IntentCompat import com.oasisfeng.android.ui.Dialogs +import com.oasisfeng.android.util.Apps import com.oasisfeng.android.widget.Toasts import com.oasisfeng.common.app.BaseAndroidViewModel import com.oasisfeng.island.analytics.Analytics.Param.ITEM_CATEGORY @@ -68,7 +69,7 @@ object IslandAppControl { return analytics().event("app_launch_error").with(ITEM_ID, pkg).with(ITEM_CATEGORY, failure).send() } if (! IslandManager.launchApp(context, pkg, app.user)) { - Toast.makeText(context, R.string.toast_app_launch_failure, Toast.LENGTH_LONG).show() + Toast.makeText(context, context.getString(R.string.toast_app_launch_failure, Apps.of(context).getAppName(pkg)), Toast.LENGTH_LONG).show() analytics().event("app_launch_error").with(ITEM_ID, pkg).with(ITEM_CATEGORY, "launcher_activity_not_found").send() } } diff --git a/mobile/src/main/java/com/oasisfeng/island/settings/AppOpsPermissionsUnlock.kt b/mobile/src/main/java/com/oasisfeng/island/settings/AppOpsPermissionsUnlock.kt index d19f478af..d5dd64273 100644 --- a/mobile/src/main/java/com/oasisfeng/island/settings/AppOpsPermissionsUnlock.kt +++ b/mobile/src/main/java/com/oasisfeng/island/settings/AppOpsPermissionsUnlock.kt @@ -8,7 +8,10 @@ import android.content.Context import android.content.Intent import android.content.pm.ApplicationInfo import android.content.pm.PackageInfo -import android.content.pm.PackageManager.* +import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED +import android.content.pm.PackageManager.DONT_KILL_APP +import android.content.pm.PackageManager.GET_PERMISSIONS +import android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES import android.os.Build.VERSION.SDK_INT import android.os.Build.VERSION_CODES.P import android.util.Log diff --git a/mobile/src/main/java/com/oasisfeng/island/settings/IslandNameManager.kt b/mobile/src/main/java/com/oasisfeng/island/settings/IslandNameManager.kt index 24a647a44..4951e9c1b 100644 --- a/mobile/src/main/java/com/oasisfeng/island/settings/IslandNameManager.kt +++ b/mobile/src/main/java/com/oasisfeng/island/settings/IslandNameManager.kt @@ -22,7 +22,8 @@ object IslandNameManager { } fun getDefaultName(context: Context, profile: UserHandle = Users.current()) = - if (Users.getProfilesManagedByIsland().size > 1) getDefaultSpecificName(context, profile) else context.getString(R.string.default_island_name) + if (Users.getProfilesManagedByIsland().size > 1) getDefaultSpecificName(context, profile) + else context.getString(if (Users.isOwner(profile)) R.string.tab_mainland else R.string.default_island_name) private fun getDefaultSpecificName(context: Context, profile: UserHandle = Users.current()) = when (val profileId = profile.toId()) { 0 -> context.getString(R.string.tab_mainland) diff --git a/mobile/src/main/java/com/oasisfeng/island/settings/OpsManager.kt b/mobile/src/main/java/com/oasisfeng/island/settings/OpsManager.kt index b4825c3b0..0b880bab7 100644 --- a/mobile/src/main/java/com/oasisfeng/island/settings/OpsManager.kt +++ b/mobile/src/main/java/com/oasisfeng/island/settings/OpsManager.kt @@ -91,7 +91,7 @@ import kotlinx.coroutines.withContext val pkg: String = info.packageName val mRevoked = mOpsRevokedPkgs.contains(pkg) - internal val mSystem = Apps.isSystem(info) + val mSystem = Apps.isSystem(info) } private val mAppsHelper = Apps.of(activity) diff --git a/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt b/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt index a2f4b34a9..b7f45fa1d 100644 --- a/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt +++ b/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt @@ -33,6 +33,7 @@ import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.graphics.drawable.IconCompat import com.oasisfeng.android.content.pm.LauncherAppsCompat import com.oasisfeng.android.os.UserHandles +import com.oasisfeng.android.util.Apps import com.oasisfeng.island.analytics.analytics import com.oasisfeng.island.data.IslandAppInfo import com.oasisfeng.island.data.helper.hidden @@ -188,7 +189,7 @@ object IslandAppShortcut { @OwnerUser private fun prepareAndLaunch(context: Context, pkg: String, intent: Intent? = null, profile: UserHandle = Users.current()) { val app = LauncherAppsCompat(context).getApplicationInfoNoThrows(pkg, MATCH_UNINSTALLED_PACKAGES, profile) - ?: return Toast.makeText(context, R.string.toast_app_launch_failure, LENGTH_LONG).show() + ?: return Toast.makeText(context, context.getString(R.string.toast_app_launch_failure, Apps.of(context).getAppName(pkg)), LENGTH_LONG).show() Shuttle(context, to = profile).launch(at = GlobalScope, alwaysByActivity = false) { if (app.hidden) IslandManager.ensureAppFreeToLaunch(this, pkg) launch(this, pkg, intent) } diff --git a/mobile/src/main/res/values-zh-rTW/strings.xml b/mobile/src/main/res/values-zh-rTW/strings.xml index 25c034a25..41b765833 100644 --- a/mobile/src/main/res/values-zh-rTW/strings.xml +++ b/mobile/src/main/res/values-zh-rTW/strings.xml @@ -122,7 +122,7 @@ 無法凍結已啟用裝置管理器的應用程式 文件傳送門需要“儲存”權限以打通檔案瀏覽。 抱歉,啟動應用程式時出現了異常。 - 未能啟動“%s” + 未能啟動 %s 快速啟動方式已失效,請重新建立 操作失敗\n(可能由於 ROM 兼容性) diff --git a/mobile/src/main/res/values-zh/strings.xml b/mobile/src/main/res/values-zh/strings.xml index af9df88f5..da9239f08 100644 --- a/mobile/src/main/res/values-zh/strings.xml +++ b/mobile/src/main/res/values-zh/strings.xml @@ -121,7 +121,7 @@ 无法冻结已激活设备管理器的应用 文件传送门需要“存储”权限以打通文件访问。 抱歉,启动应用时出现了异常。 - 未能启动“%s” + 未能启动 %s 快捷方式已失效,请重新创建 操作失败\n(可能由于 ROM 兼容性) diff --git a/mobile/src/main/res/values/strings.xml b/mobile/src/main/res/values/strings.xml index 7169027f7..b7b44e501 100644 --- a/mobile/src/main/res/values/strings.xml +++ b/mobile/src/main/res/values/strings.xml @@ -124,7 +124,7 @@ the sandbox environment. Island never collect data related to your privacy, plea Cannot freeze active device-admin Storage permission is required to access the shared storage from within Island. Sorry, there\'s an error launching this app. - Could not launch \"%s\" + Failed to launch %s Invalid shortcut, please recreate. Operation failed.\n(probably due to ROM compatibility) diff --git a/open/src/main/java/com/oasisfeng/island/api/DelegatedAppOpsManager.java b/open/src/main/java/com/oasisfeng/island/api/DelegatedAppOpsManager.java index 717162e0d..6c5f66b45 100644 --- a/open/src/main/java/com/oasisfeng/island/api/DelegatedAppOpsManager.java +++ b/open/src/main/java/com/oasisfeng/island/api/DelegatedAppOpsManager.java @@ -89,7 +89,7 @@ private static class AppOpsBinderProxy extends RestrictedBinderProxy { Log.i(TAG, "IAppOpsService.setMode(" + op + ", " + uid + ", " + pkg + ", " + mode + ")"); final @UserIdInt int user_id = UserHandles.getUserId(uid); - if (user_id == UserHandles.getIdentifier(Users.current())) { + if (user_id == Users.currentId()) { new AppOpsHelper(mContext).setMode(pkg, op, mode, uid); return true; } diff --git a/shared/build.gradle b/shared/build.gradle index bd92937b0..43dbf7bb6 100644 --- a/shared/build.gradle +++ b/shared/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdkVersion 29 // Not raised to 28 due to NotificationManagerExtender + compileSdkVersion 30 defaultConfig { minSdkVersion this.minSdkVersion diff --git a/shared/src/main/AndroidManifest.xml b/shared/src/main/AndroidManifest.xml index aa0bf1d01..6beb4fc27 100644 --- a/shared/src/main/AndroidManifest.xml +++ b/shared/src/main/AndroidManifest.xml @@ -12,9 +12,9 @@ - diff --git a/shared/src/main/java/com/oasisfeng/island/InternalContentProviders.java b/shared/src/main/java/com/oasisfeng/island/InternalContentProviders.java deleted file mode 100644 index 1a42e6ec1..000000000 --- a/shared/src/main/java/com/oasisfeng/island/InternalContentProviders.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.oasisfeng.island; - -/** - * Manifest stub for internal content providers - * - * Created by Oasis on 2017/7/14. - */ -public class InternalContentProviders { - - public static class _1 extends com.oasisfeng.island.util.Users {} -} diff --git a/shared/src/main/java/com/oasisfeng/island/util/Modules.java b/shared/src/main/java/com/oasisfeng/island/util/Modules.java index 1ea876e24..375938698 100644 --- a/shared/src/main/java/com/oasisfeng/island/util/Modules.java +++ b/shared/src/main/java/com/oasisfeng/island/util/Modules.java @@ -44,12 +44,12 @@ public static void broadcast(final Context context, final Intent intent) { final String my_pkg = context.getPackageName(); final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE).setPackage(my_pkg); // First query in current package final PackageManager pm = context.getPackageManager(); - List resolves = pm.queryIntentContentProviders(intent, GET_DISABLED_COMPONENTS); - if (resolves != null && ! resolves.isEmpty()) { + List resolves = pm.queryIntentContentProviders(intent, MATCH_DISABLED_COMPONENTS); + if (! resolves.isEmpty()) { if (resolves.size() > 1) throw new IllegalStateException("More than 1 file provider: " + resolves); return sFileProviderComponent = new ComponentName(my_pkg, resolves.get(0).providerInfo.name); } - resolves = pm.queryIntentContentProviders(intent.setPackage(null), GET_DISABLED_COMPONENTS); // Query in UID-shared packages + resolves = pm.queryIntentContentProviders(intent.setPackage(null), MATCH_DISABLED_COMPONENTS); // Query in UID-shared packages final int my_uid = Process.myUid(); for (final ResolveInfo resolve : resolves) { final ProviderInfo provider = resolve.providerInfo; diff --git a/shared/src/main/java/com/oasisfeng/island/util/ProfileUser.java b/shared/src/main/java/com/oasisfeng/island/util/ProfileUser.java index 2b5b431d1..2af16eb6e 100644 --- a/shared/src/main/java/com/oasisfeng/island/util/ProfileUser.java +++ b/shared/src/main/java/com/oasisfeng/island/util/ProfileUser.java @@ -4,6 +4,7 @@ import java.lang.annotation.Target; import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -14,5 +15,5 @@ * Created by Oasis on 2016/11/27. */ @Retention(SOURCE) -@Target({TYPE,METHOD,CONSTRUCTOR}) +@Target({TYPE,METHOD,CONSTRUCTOR,FIELD}) public @interface ProfileUser {} diff --git a/shared/src/main/java/com/oasisfeng/island/util/Users.java b/shared/src/main/java/com/oasisfeng/island/util/Users.java index aaea337c0..4147515f4 100644 --- a/shared/src/main/java/com/oasisfeng/island/util/Users.java +++ b/shared/src/main/java/com/oasisfeng/island/util/Users.java @@ -32,7 +32,7 @@ * * Created by Oasis on 2016/9/25. */ -public abstract class Users extends PseudoContentProvider { +public class Users extends PseudoContentProvider { public static @Nullable UserHandle profile; // The first profile managed by Island (semi-immutable, until profile is created or destroyed) public static UserHandle owner; // TODO: Rename to "parent" @@ -46,9 +46,11 @@ public abstract class Users extends PseudoContentProvider { public static int currentId() { return CURRENT_ID; } @Override public boolean onCreate() { + Log.v(TAG, "onCreate()"); final int priority = IntentFilter.SYSTEM_HIGH_PRIORITY - 1; - context().registerReceiver(mProfileChangeObserver, IntentFilters.forActions(Intent.ACTION_MANAGED_PROFILE_ADDED, // ACTION_MANAGED_PROFILE_ADDED is sent by DevicePolicyManagerService.setProfileEnabled() - Intent.ACTION_MANAGED_PROFILE_REMOVED, DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED).inPriority(priority)); // ACTION_PROFILE_OWNER_CHANGED is sent after "dpm set-profile-owner ..." + @SuppressLint("InlinedApi") final String ACTION_PROFILE_OWNER_CHANGED = DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED; + context().registerReceiver(mProfileChangeObserver, IntentFilters.forActions(Intent.ACTION_MANAGED_PROFILE_ADDED,// ACTION_MANAGED_PROFILE_ADDED is sent by DevicePolicyManagerService.setProfileEnabled() + Intent.ACTION_MANAGED_PROFILE_REMOVED, ACTION_PROFILE_OWNER_CHANGED).inPriority(priority)); // ACTION_PROFILE_OWNER_CHANGED is sent after "dpm set-profile-owner ..." refreshUsers(context()); return true; } diff --git a/shared/src/main/java/com/oasisfeng/settings/AppSettingsProvider.kt b/shared/src/main/java/com/oasisfeng/settings/AppSettingsProvider.kt index d83c424bc..b334df38c 100644 --- a/shared/src/main/java/com/oasisfeng/settings/AppSettingsProvider.kt +++ b/shared/src/main/java/com/oasisfeng/settings/AppSettingsProvider.kt @@ -1,6 +1,9 @@ package com.oasisfeng.settings -import android.content.* +import android.content.ComponentName +import android.content.ContentProvider +import android.content.ContentValues +import android.content.Intent import android.content.pm.PackageManager import android.database.Cursor import android.database.MatrixCursor @@ -76,7 +79,7 @@ class AppSettingsProvider : ContentProvider() { override fun insert(uri: Uri, values: ContentValues?): Uri? = null override fun delete(uri: Uri, selection: String?, selectionArgs: Array?) = 0 - private val mSharedPrefs by lazy @Suppress("DEPRECATION") { + private val mSharedPrefs by lazy { @Suppress("DEPRECATION") android.preference.PreferenceManager.getDefaultSharedPreferences(context()) } } diff --git a/watcher/src/main/java/com/oasisfeng/island/watcher/IslandWatcher.kt b/watcher/src/main/java/com/oasisfeng/island/watcher/IslandWatcher.kt index 86c0f7148..5b9dd7a55 100644 --- a/watcher/src/main/java/com/oasisfeng/island/watcher/IslandWatcher.kt +++ b/watcher/src/main/java/com/oasisfeng/island/watcher/IslandWatcher.kt @@ -85,10 +85,10 @@ import kotlin.coroutines.suspendCoroutine if (Users.isOwner()) { intent?.getParcelableExtra(Intent.EXTRA_USER)?.also { profile -> GlobalScope.launch { requestQuietModeApi29(this@IslandDeactivationService, profile) } - return START_STICKY } // Still ongoing - } else Shuttle(this, Users.owner).launch(at = GlobalScope, with = Users.current()) { - startService(Intent(this, IslandDeactivationService::class.java).putExtra(Intent.EXTRA_USER, it)) } - } else requestQuietMode(Users.current()) + return START_STICKY }} // Still ongoing + else Shuttle(this, to = Users.owner).launch(with = Users.current()) { + startService(Intent(this, IslandDeactivationService::class.java).putExtra(Intent.EXTRA_USER, it)) }} + else requestQuietMode(Users.current()) stopSelf() return START_NOT_STICKY } @@ -111,8 +111,7 @@ import kotlin.coroutines.suspendCoroutine pm.setComponentEnabledSetting(dummyHome, COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP) val user = result.getParcelableExtra(Intent.EXTRA_USER) Log.i(TAG, "Island is deactivated: ${user?.toId()}") - return Toasts.showShort(context, "Island is deactivated.") - } + return Toasts.showShort(context, "Island is deactivated.") } } private fun makeDefaultHome(home: ComponentName): Boolean {