1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.settings.applications.appinfo; 17 18 import static android.app.Activity.RESULT_CANCELED; 19 import static android.app.Activity.RESULT_OK; 20 21 import android.app.AlertDialog; 22 import android.app.AppOpsManager; 23 import android.content.Context; 24 import android.os.Bundle; 25 import android.os.UserHandle; 26 import android.os.UserManager; 27 import android.support.v7.preference.Preference; 28 import android.support.v7.preference.Preference.OnPreferenceChangeListener; 29 30 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 31 import com.android.settings.R; 32 import com.android.settings.Settings; 33 import com.android.settings.applications.AppInfoWithHeader; 34 import com.android.settings.applications.AppStateInstallAppsBridge; 35 import com.android.settings.applications.AppStateInstallAppsBridge.InstallAppsState; 36 import com.android.settingslib.RestrictedSwitchPreference; 37 import com.android.settingslib.applications.ApplicationsState.AppEntry; 38 39 public class ExternalSourcesDetails extends AppInfoWithHeader 40 implements OnPreferenceChangeListener { 41 42 private static final String KEY_EXTERNAL_SOURCE_SWITCH = "external_sources_settings_switch"; 43 44 private AppStateInstallAppsBridge mAppBridge; 45 private AppOpsManager mAppOpsManager; 46 private UserManager mUserManager; 47 private RestrictedSwitchPreference mSwitchPref; 48 private InstallAppsState mInstallAppsState; 49 50 @Override 51 public void onCreate(Bundle savedInstanceState) { 52 super.onCreate(savedInstanceState); 53 54 final Context context = getActivity(); 55 mAppBridge = new AppStateInstallAppsBridge(context, mState, null); 56 mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 57 mUserManager = UserManager.get(context); 58 59 addPreferencesFromResource(R.xml.external_sources_details); 60 mSwitchPref = (RestrictedSwitchPreference) findPreference(KEY_EXTERNAL_SOURCE_SWITCH); 61 mSwitchPref.setOnPreferenceChangeListener(this); 62 } 63 64 @Override 65 public boolean onPreferenceChange(Preference preference, Object newValue) { 66 final boolean checked = (Boolean) newValue; 67 if (preference == mSwitchPref) { 68 if (mInstallAppsState != null && checked != mInstallAppsState.canInstallApps()) { 69 if (Settings.ManageAppExternalSourcesActivity.class.getName().equals( 70 getIntent().getComponent().getClassName())) { 71 setResult(checked ? RESULT_OK : RESULT_CANCELED); 72 } 73 setCanInstallApps(checked); 74 refreshUi(); 75 } 76 return true; 77 } 78 return false; 79 } 80 81 public static CharSequence getPreferenceSummary(Context context, AppEntry entry) { 82 final UserManager um = UserManager.get(context); 83 final int userRestrictionSource = um.getUserRestrictionSource( 84 UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, 85 UserHandle.getUserHandleForUid(entry.info.uid)); 86 switch (userRestrictionSource) { 87 case UserManager.RESTRICTION_SOURCE_DEVICE_OWNER: 88 case UserManager.RESTRICTION_SOURCE_PROFILE_OWNER: 89 return context.getString(R.string.disabled_by_admin); 90 case UserManager.RESTRICTION_SOURCE_SYSTEM: 91 return context.getString(R.string.disabled); 92 } 93 94 final InstallAppsState appsState = new AppStateInstallAppsBridge(context, null, null) 95 .createInstallAppsStateFor(entry.info.packageName, entry.info.uid); 96 97 return context.getString(appsState.canInstallApps() 98 ? R.string.app_permission_summary_allowed 99 : R.string.app_permission_summary_not_allowed); 100 } 101 102 private void setCanInstallApps(boolean newState) { 103 mAppOpsManager.setMode(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, 104 mPackageInfo.applicationInfo.uid, mPackageName, 105 newState ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_ERRORED); 106 } 107 108 @Override 109 protected boolean refreshUi() { 110 if (mPackageInfo == null || mPackageInfo.applicationInfo == null) { 111 return false; 112 } 113 if (mUserManager.hasBaseUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, 114 UserHandle.of(UserHandle.myUserId()))) { 115 mSwitchPref.setChecked(false); 116 mSwitchPref.setSummary(R.string.disabled); 117 mSwitchPref.setEnabled(false); 118 return true; 119 } 120 mSwitchPref.checkRestrictionAndSetDisabled(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES); 121 if (mSwitchPref.isDisabledByAdmin()) { 122 return true; 123 } 124 mInstallAppsState = mAppBridge.createInstallAppsStateFor(mPackageName, 125 mPackageInfo.applicationInfo.uid); 126 if (!mInstallAppsState.isPotentialAppSource()) { 127 // Invalid app entry. Should not allow changing permission 128 mSwitchPref.setEnabled(false); 129 return true; 130 } 131 mSwitchPref.setChecked(mInstallAppsState.canInstallApps()); 132 return true; 133 } 134 135 @Override 136 protected AlertDialog createDialog(int id, int errorCode) { 137 return null; 138 } 139 140 @Override 141 public int getMetricsCategory() { 142 return MetricsEvent.MANAGE_EXTERNAL_SOURCES; 143 } 144 } 145