Skip to content

Commit

Permalink
UPDATE: Minor tweaks.
Browse files Browse the repository at this point in the history
  • Loading branch information
oasisfeng committed Apr 2, 2021
1 parent 9a27fe8 commit ceb6991
Show file tree
Hide file tree
Showing 21 changed files with 52 additions and 48 deletions.
6 changes: 3 additions & 3 deletions build.gradle
@@ -1,17 +1,17 @@
// 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()
jcenter()
}
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
Expand Down
5 changes: 3 additions & 2 deletions engine/src/main/AndroidManifest.xml
Expand Up @@ -106,7 +106,7 @@
<service android:name="com.oasisfeng.island.provisioning.IslandProvisioning" android:exported="false"
android:directBootAware="true">
<intent-filter>
<action android:name="android.app.action.PROVISION_MANAGED_PROFILE" />
<action android:name="android.app.action.PROVISION_MANAGED_PROFILE" /> <!-- For re-provisioning procedure, see IslandSettingsFragment -->
<action android:name="android.app.action.PROVISION_MANAGED_DEVICE" />
</intent-filter>
</service>
Expand Down Expand Up @@ -136,7 +136,8 @@
</intent-filter>
</receiver>

<provider android:name="com.oasisfeng.island.provisioning.AutoIncrementalProvision" android:authorities="${applicationId}.AIP" android:exported="false"/>
<provider android:name="com.oasisfeng.island.provisioning.AutoIncrementalProvision"
android:authorities="${applicationId}.AIP" android:exported="false" android:initOrder="999" />

<receiver android:name="com.oasisfeng.island.AppUpdateReceiver" android:exported="false" android:directBootAware="true">
<intent-filter>
Expand Down
Expand Up @@ -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.
*/
Expand Down
Expand Up @@ -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) {
Expand Down
Expand Up @@ -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
Expand Down Expand Up @@ -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() }
}

Expand Down
Expand Up @@ -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
Expand Down
Expand Up @@ -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)
Expand Down
Expand Up @@ -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)
Expand Down
Expand Up @@ -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
Expand Down Expand Up @@ -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) }
Expand Down
2 changes: 1 addition & 1 deletion mobile/src/main/res/values-zh-rTW/strings.xml
Expand Up @@ -122,7 +122,7 @@
<string name="toast_error_freezing_active_admin">無法凍結已啟用裝置管理器的應用程式</string>
<string name="toast_external_storage_permission_required">文件傳送門需要“儲存”權限以打通檔案瀏覽。</string>
<string name="toast_app_launch_error">抱歉,啟動應用程式時出現了異常。</string>
<string name="toast_app_launch_failure">未能啟動“%s”</string>
<string name="toast_app_launch_failure">未能啟動 %s</string>
<string name="prompt_invalid_shortcut">快速啟動方式已失效,請重新建立</string>
<string name="prompt_operation_failure_due_to_incompatibility">操作失敗\n(可能由於 ROM 兼容性)</string>

Expand Down
2 changes: 1 addition & 1 deletion mobile/src/main/res/values-zh/strings.xml
Expand Up @@ -121,7 +121,7 @@
<string name="toast_error_freezing_active_admin">无法冻结已激活设备管理器的应用</string>
<string name="toast_external_storage_permission_required">文件传送门需要“存储”权限以打通文件访问。</string>
<string name="toast_app_launch_error">抱歉,启动应用时出现了异常。</string>
<string name="toast_app_launch_failure">未能启动“%s”</string>
<string name="toast_app_launch_failure">未能启动 %s</string>
<string name="prompt_invalid_shortcut">快捷方式已失效,请重新创建</string>
<string name="prompt_operation_failure_due_to_incompatibility">操作失败\n(可能由于 ROM 兼容性)</string>

Expand Down
2 changes: 1 addition & 1 deletion mobile/src/main/res/values/strings.xml
Expand Up @@ -124,7 +124,7 @@ the sandbox environment. Island never collect data related to your privacy, plea
<string name="toast_error_freezing_active_admin">Cannot freeze active device-admin</string>
<string name="toast_external_storage_permission_required">Storage permission is required to access the shared storage from within Island.</string>
<string name="toast_app_launch_error">Sorry, there\'s an error launching this app.</string>
<string name="toast_app_launch_failure">Could not launch \"%s\"</string>
<string name="toast_app_launch_failure">Failed to launch %s</string>
<string name="prompt_invalid_shortcut">Invalid shortcut, please recreate.</string>
<string name="prompt_operation_failure_due_to_incompatibility">Operation failed.\n(probably due to ROM compatibility)</string>

Expand Down
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion shared/build.gradle
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions shared/src/main/AndroidManifest.xml
Expand Up @@ -12,9 +12,9 @@
<meta-data android:name="firebase_crashlytics_collection_enabled" android:value="false" />

<!-- Users -->
<provider android:name="com.oasisfeng.island.InternalContentProviders$_1"
<provider android:name="com.oasisfeng.island.util.Users"
android:initOrder="1000"
android:authorities="${applicationId}.internal.1"
android:authorities="${applicationId}.users"
android:directBootAware="true"
android:exported="false" />

Expand Down

This file was deleted.

6 changes: 3 additions & 3 deletions shared/src/main/java/com/oasisfeng/island/util/Modules.java
Expand Up @@ -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<ResolveInfo> resolves = pm.queryIntentContentProviders(intent, GET_DISABLED_COMPONENTS);
if (resolves != null && ! resolves.isEmpty()) {
List<ResolveInfo> 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;
Expand Down
Expand Up @@ -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;
Expand All @@ -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 {}
8 changes: 5 additions & 3 deletions shared/src/main/java/com/oasisfeng/island/util/Users.java
Expand Up @@ -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"
Expand All @@ -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;
}
Expand Down
@@ -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
Expand Down Expand Up @@ -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<String>?) = 0

private val mSharedPrefs by lazy @Suppress("DEPRECATION") {
private val mSharedPrefs by lazy { @Suppress("DEPRECATION")
android.preference.PreferenceManager.getDefaultSharedPreferences(context()) }
}

Expand Down
Expand Up @@ -85,10 +85,10 @@ import kotlin.coroutines.suspendCoroutine
if (Users.isOwner()) {
intent?.getParcelableExtra<UserHandle>(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
}
Expand All @@ -111,8 +111,7 @@ import kotlin.coroutines.suspendCoroutine
pm.setComponentEnabledSetting(dummyHome, COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP)
val user = result.getParcelableExtra<UserHandle>(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 {
Expand Down

0 comments on commit ceb6991

Please sign in to comment.