19f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/* 2f04335f899f2cce69f843692a3cb9cec229683c2tturney * Copyright (C) 2017 The Android Open Source Project 39f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 4f04335f899f2cce69f843692a3cb9cec229683c2tturney * Licensed under the Apache License, Version 2.0 (the "License"); 5f04335f899f2cce69f843692a3cb9cec229683c2tturney * you may not use this file except in compliance with the License. 6f04335f899f2cce69f843692a3cb9cec229683c2tturney * You may obtain a copy of the License at 79f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 8f04335f899f2cce69f843692a3cb9cec229683c2tturney * http://www.apache.org/licenses/LICENSE-2.0 99f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Unless required by applicable law or agreed to in writing, software 11f04335f899f2cce69f843692a3cb9cec229683c2tturney * distributed under the License is distributed on an "AS IS" BASIS, 12f04335f899f2cce69f843692a3cb9cec229683c2tturney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f04335f899f2cce69f843692a3cb9cec229683c2tturney * See the License for the specific language governing permissions and 14f04335f899f2cce69f843692a3cb9cec229683c2tturney * limitations under the License. 159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipackage com.googlecode.android_scripting.interpreter; 189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.BroadcastReceiver; 209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.ContentResolver; 219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.Context; 229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.Intent; 239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.IntentFilter; 249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.pm.PackageInfo; 259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.pm.PackageManager; 269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.pm.ProviderInfo; 279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.pm.ResolveInfo; 289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.pm.PackageManager.NameNotFoundException; 299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.database.Cursor; 309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.net.Uri; 319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.Log; 339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.SingleThreadExecutor; 349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.interpreter.shell.ShellInterpreter; 359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.ArrayList; 379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.HashMap; 389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.LinkedHashMap; 399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.List; 409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.Map; 419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.Set; 429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.concurrent.CopyOnWriteArraySet; 439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.concurrent.ExecutorService; 449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/** 469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Manages and provides access to the set of available interpreters. 479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipublic class InterpreterConfiguration { 509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final InterpreterListener mListener; 529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Set<Interpreter> mInterpreterSet; 539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Set<ConfigurationObserver> mObserverSet; 549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Context mContext; 559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private volatile boolean mIsDiscoveryComplete = false; 569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public interface ConfigurationObserver { 589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onConfigurationChanged(); 599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private class InterpreterListener extends BroadcastReceiver { 629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final PackageManager mmPackageManager; 639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final ContentResolver mmResolver; 649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final ExecutorService mmExecutor; 659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Map<String, Interpreter> mmDiscoveredInterpreters; 669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private InterpreterListener(Context context) { 689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mmPackageManager = context.getPackageManager(); 699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mmResolver = context.getContentResolver(); 709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mmExecutor = new SingleThreadExecutor(); 719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mmDiscoveredInterpreters = new HashMap<String, Interpreter>(); 729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void discoverForType(final String mime) { 759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mmExecutor.execute(new Runnable() { 769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void run() { 789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Intent intent = new Intent(InterpreterConstants.ACTION_DISCOVER_INTERPRETERS); 799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li intent.addCategory(Intent.CATEGORY_LAUNCHER); 809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li intent.setType(mime); 819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li List<ResolveInfo> resolveInfos = mmPackageManager.queryIntentActivities(intent, 0); 829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (ResolveInfo info : resolveInfos) { 839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li addInterpreter(info.activityInfo.packageName); 849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mIsDiscoveryComplete = true; 869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li notifyConfigurationObservers(); 879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li }); 899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void discoverAll() { 929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mmExecutor.execute(new Runnable() { 939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void run() { 959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Intent intent = new Intent(InterpreterConstants.ACTION_DISCOVER_INTERPRETERS); 969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li intent.addCategory(Intent.CATEGORY_LAUNCHER); 979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li intent.setType(InterpreterConstants.MIME + "*"); 989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li List<ResolveInfo> resolveInfos = mmPackageManager.queryIntentActivities(intent, 0); 999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (ResolveInfo info : resolveInfos) { 1009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li addInterpreter(info.activityInfo.packageName); 1019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mIsDiscoveryComplete = true; 1039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li notifyConfigurationObservers(); 1049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li }); 1069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void notifyConfigurationObservers() { 1099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (ConfigurationObserver observer : mObserverSet) { 1109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li observer.onConfigurationChanged(); 1119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void addInterpreter(final String packageName) { 1159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mmDiscoveredInterpreters.containsKey(packageName)) { 1169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 1179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Interpreter discoveredInterpreter = buildInterpreter(packageName); 1199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (discoveredInterpreter == null) { 1209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 1219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mmDiscoveredInterpreters.put(packageName, discoveredInterpreter); 1239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mInterpreterSet.add(discoveredInterpreter); 1249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.v("Interpreter discovered: " + packageName + "\nBinary: " 1259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li + discoveredInterpreter.getBinary()); 1269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void remove(final String packageName) { 1299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (!mmDiscoveredInterpreters.containsKey(packageName)) { 1309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 1319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mmExecutor.execute(new Runnable() { 1339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void run() { 1359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Interpreter interpreter = mmDiscoveredInterpreters.get(packageName); 1369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (interpreter == null) { 1379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.v("Interpreter for " + packageName + " not installed."); 1389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 1399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mInterpreterSet.remove(interpreter); 1419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mmDiscoveredInterpreters.remove(packageName); 1429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li notifyConfigurationObservers(); 1439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li }); 1459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // We require that there's only one interpreter provider per APK. 1489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private Interpreter buildInterpreter(String packageName) { 1499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li PackageInfo packInfo; 1509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li try { 1519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li packInfo = mmPackageManager.getPackageInfo(packageName, PackageManager.GET_PROVIDERS); 1529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } catch (NameNotFoundException e) { 1539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li throw new RuntimeException("Package '" + packageName + "' not found."); 1549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ProviderInfo provider = packInfo.providers[0]; 1569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Map<String, String> interpreterMap = 1589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li getMap(provider, InterpreterConstants.PROVIDER_PROPERTIES); 1599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (interpreterMap == null) { 1609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.e("Null interpreter map for: " + packageName); 1619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return null; 1629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Map<String, String> environmentMap = 1649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li getMap(provider, InterpreterConstants.PROVIDER_ENVIRONMENT_VARIABLES); 1659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (environmentMap == null) { 1669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li throw new RuntimeException("Null environment map for: " + packageName); 1679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Map<String, String> argumentsMap = getMap(provider, InterpreterConstants.PROVIDER_ARGUMENTS); 1699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (argumentsMap == null) { 1709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li throw new RuntimeException("Null arguments map for: " + packageName); 1719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return Interpreter.buildFromMaps(interpreterMap, environmentMap, argumentsMap); 1739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private Map<String, String> getMap(ProviderInfo provider, String name) { 1769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Uri uri = Uri.parse("content://" + provider.authority + "/" + name); 1779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Cursor cursor = mmResolver.query(uri, null, null, null, null); 1789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (cursor == null) { 1799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return null; 1809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li cursor.moveToFirst(); 1829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Use LinkedHashMap so that order is maintained (important for position CLI arguments). 1839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Map<String, String> map = new LinkedHashMap<String, String>(); 1849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (int i = 0; i < cursor.getColumnCount(); i++) { 1859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li map.put(cursor.getColumnName(i), cursor.getString(i)); 1869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return map; 1889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onReceive(Context context, Intent intent) { 1929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li final String action = intent.getAction(); 1939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li final String packageName = intent.getData().getSchemeSpecificPart(); 1949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (action.equals(InterpreterConstants.ACTION_INTERPRETER_ADDED)) { 1959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mmExecutor.execute(new Runnable() { 1969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void run() { 1989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li addInterpreter(packageName); 1999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li notifyConfigurationObservers(); 2009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li }); 2029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (action.equals(InterpreterConstants.ACTION_INTERPRETER_REMOVED) 2039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li || action.equals(Intent.ACTION_PACKAGE_REMOVED) 2049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li || action.equals(Intent.ACTION_PACKAGE_REPLACED) 2059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li || action.equals(Intent.ACTION_PACKAGE_DATA_CLEARED)) { 2069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li remove(packageName); 2079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public InterpreterConfiguration(Context context) { 2139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mContext = context; 2149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mInterpreterSet = new CopyOnWriteArraySet<Interpreter>(); 2159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mInterpreterSet.add(new ShellInterpreter()); 2169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mObserverSet = new CopyOnWriteArraySet<ConfigurationObserver>(); 2179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li IntentFilter filter = new IntentFilter(); 2189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li filter.addAction(InterpreterConstants.ACTION_INTERPRETER_ADDED); 2199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li filter.addAction(InterpreterConstants.ACTION_INTERPRETER_REMOVED); 2209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li filter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); 2219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 2229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li filter.addAction(Intent.ACTION_PACKAGE_REPLACED); 2239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li filter.addDataScheme("package"); 2249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mListener = new InterpreterListener(mContext); 2259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mContext.registerReceiver(mListener, filter); 2269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void startDiscovering() { 2299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mListener.discoverAll(); 2309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void startDiscovering(String mime) { 2339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mListener.discoverForType(mime); 2349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public boolean isDiscoveryComplete() { 2379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mIsDiscoveryComplete; 2389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void registerObserver(ConfigurationObserver observer) { 2419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (observer != null) { 2429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mObserverSet.add(observer); 2439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void unregisterObserver(ConfigurationObserver observer) { 2479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (observer != null) { 2489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mObserverSet.remove(observer); 2499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 2539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Returns the list of all known interpreters. 2549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 2559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public List<? extends Interpreter> getSupportedInterpreters() { 2569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return new ArrayList<Interpreter>(mInterpreterSet); 2579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 2609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Returns the list of all installed interpreters. 2619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 2629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public List<Interpreter> getInstalledInterpreters() { 2639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li List<Interpreter> interpreters = new ArrayList<Interpreter>(); 2649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (Interpreter i : mInterpreterSet) { 2659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (i.isInstalled()) { 2669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li interpreters.add(i); 2679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return interpreters; 2709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 2739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Returns the list of interpreters that support interactive mode execution. 2749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 2759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public List<Interpreter> getInteractiveInterpreters() { 2769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li List<Interpreter> interpreters = new ArrayList<Interpreter>(); 2779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (Interpreter i : mInterpreterSet) { 2789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (i.isInstalled() && i.hasInteractiveMode()) { 2799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li interpreters.add(i); 2809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return interpreters; 2839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 2869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Returns the interpreter matching the provided name or null if no interpreter was found. 2879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 2889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public Interpreter getInterpreterByName(String interpreterName) { 2899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (Interpreter i : mInterpreterSet) { 2909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (i.getName().equals(interpreterName)) { 2919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return i; 2929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return null; 2959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 2989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Returns the correct interpreter for the provided script name based on the script's extension or 2999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * null if no interpreter was found. 3009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 3019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public Interpreter getInterpreterForScript(String scriptName) { 3029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int dotIndex = scriptName.lastIndexOf('.'); 3039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (dotIndex == -1) { 3049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return null; 3059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String ext = scriptName.substring(dotIndex); 3079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (Interpreter i : mInterpreterSet) { 3089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (i.getExtension().equals(ext)) { 3099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return i; 3109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return null; 3139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li} 315