下面列出了android.support.annotation.BinderThread#org.chromium.base.ThreadUtils 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/** Moves the user to tabbed mode by opting them out and removing all the tasks. */
final void switchToTabbedMode() {
ThreadUtils.assertOnUiThread();
if (!setStage(STAGE_WRITE_TABMODEL_METADATA_DONE, STAGE_CHANGE_SETTINGS_STARTED)) return;
// Record that the user has opted-out of document mode now that their data has been
// safely copied to the other directory.
Log.d(TAG, "Setting tabbed mode preference.");
setOptedOutState(OPTED_OUT_OF_DOCUMENT_MODE);
TabSwitcherCallout.setIsTabSwitcherCalloutNecessary(true);
// Remove all the {@link DocumentActivity} tasks from Android's Recents list. Users
// viewing Recents during migration will continue to see their tabs until they exit.
// Reselecting a migrated tab will kick the user to the launcher without crashing.
// TODO(dfalcantara): Confirm that the different Android flavors work the same way.
createActivityDelegate().finishAllDocumentActivities();
// Dismiss the "Close all incognito tabs" notification.
IncognitoNotificationManager.dismissIncognitoNotification();
setStage(STAGE_CHANGE_SETTINGS_STARTED, STAGE_CHANGE_SETTINGS_DONE);
}
private static LruCache<String, Pair<Bitmap, Integer>> getBitmapCache() {
ThreadUtils.assertOnUiThread();
LruCache<String, Pair<Bitmap, Integer>> cache =
sBitmapCache == null ? null : sBitmapCache.get();
if (cache != null) return cache;
// Create a new weakly-referenced cache.
cache = new LruCache<String, Pair<Bitmap, Integer>>(MAX_CACHE_BYTES) {
@Override
protected int sizeOf(String key, Pair<Bitmap, Integer> thumbnail) {
return thumbnail == null ? 0 : thumbnail.second;
}
};
sBitmapCache = new WeakReference<>(cache);
return cache;
}
/**
* Performs an asynchronous check to see if the user is a managed user.
* @param callback A callback to be called with true if the user is a managed user and false
* otherwise.
*/
public static void isUserManaged(String email, final Callback<Boolean> callback) {
if (nativeShouldLoadPolicyForUser(email)) {
nativeIsUserManaged(email, callback);
} else {
// Although we know the result immediately, the caller may not be able to handle the
// callback being executed during this method call. So we post the callback on the
// looper.
ThreadUtils.postOnUiThread(new Runnable() {
@Override
public void run() {
callback.onResult(false);
}
});
}
}
/**
* Retrieves the connectivity that has been collected up until this call. This method fills in
* {@link ConnectivityCheckResult#UNKNOWN} for results that have not been retrieved yet.
*
* @return the {@link FeedbackData}.
*/
public FeedbackData get() {
ThreadUtils.assertOnUiThread();
Map<Type, Integer> result = new EnumMap<Type, Integer>(Type.class);
// Ensure the map is filled with a result for all {@link Type}s.
for (Type type : Type.values()) {
if (mResult.containsKey(type)) {
result.put(type, mResult.get(type));
} else {
result.put(type, ConnectivityCheckResult.UNKNOWN);
}
}
long elapsedTimeMs = SystemClock.elapsedRealtime() - mStartCheckTimeMs;
int connectionType = NetworkChangeNotifier.getInstance().getCurrentConnectionType();
return new FeedbackData(result, mTimeoutMs, elapsedTimeMs, connectionType);
}
protected TtsPlatformImpl(long nativeTtsPlatformImplAndroid, Context context) {
mInitialized = false;
mNativeTtsPlatformImplAndroid = nativeTtsPlatformImplAndroid;
mTextToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
initialize();
}
});
}
}
});
addOnUtteranceProgressListener();
}
@Override
public void onTrimMemory(final int level) {
ThreadUtils.assertOnUiThread();
LauncherThread.post(new Runnable() {
@Override
public void run() {
Log.i(TAG, "onTrimMemory: level=%d, size=%d", level, mConnections.size());
if (mConnections.isEmpty()) {
return;
}
if (level <= TRIM_MEMORY_RUNNING_MODERATE) {
reduce(MODERATE_BINDING_LOW_REDUCE_RATIO);
} else if (level <= TRIM_MEMORY_RUNNING_LOW) {
reduce(MODERATE_BINDING_HIGH_REDUCE_RATIO);
} else if (level == TRIM_MEMORY_UI_HIDDEN) {
// This will be handled by |mDelayedClearer|.
return;
} else {
removeAllConnections();
}
}
});
}
/**
* Register a StartupCallback to initialize the native portion of the JNI bridge.
*/
private void registerNativeInitStartupCallback() {
ThreadUtils.postOnUiThread(new Runnable() {
@Override
public void run() {
BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
.addStartupCompletedObserver(new StartupCallback() {
@Override
public void onSuccess(boolean alreadyStarted) {
mNativePhysicalWebDataSourceAndroid = nativeInit();
for (UrlInfo urlInfo : getUrls()) {
safeNotifyNativeListenersOnFound(urlInfo.getUrl());
}
}
@Override
public void onFailure() {
// Startup failed.
}
});
}
});
}
/**
* Finishes the activity and removes the reference from the Android recents.
*
* @param reparenting true iff the activity finishes due to tab reparenting.
*/
public final void finishAndClose(boolean reparenting) {
mIsClosing = true;
if (!reparenting) {
// Closing the activity destroys the renderer as well. Re-create a spare renderer some
// time after, so that we have one ready for the next tab open. This does not increase
// memory consumption, as the current renderer goes away. We create a renderer as a lot
// of users open several Custom Tabs in a row. The delay is there to avoid jank in the
// transition animation when closing the tab.
ThreadUtils.postOnUiThreadDelayed(new Runnable() {
@Override
public void run() {
WarmupManager.getInstance().createSpareWebContents();
}
}, 500);
}
handleFinishAndClose();
}
private void preInflationStartup() {
ThreadUtils.assertOnUiThread();
if (mPreInflationStartupComplete) return;
PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
// Ensure critical files are available, so they aren't blocked on the file-system
// behind long-running accesses in next phase.
// Don't do any large file access here!
ContentApplication.initCommandLine(mApplication);
waitForDebuggerIfNeeded();
ChromeStrictMode.configureStrictMode();
ChromeWebApkHost.init();
warmUpSharedPrefs();
DeviceUtils.addDeviceSpecificUserAgentSwitch(mApplication);
ApplicationStatus.registerStateListenerForAllActivities(
createActivityStateListener());
mPreInflationStartupComplete = true;
}
@SuppressLint("NewApi")
private void notifyChange(final Uri uri) {
// If the calling user is different than current one, we need to post a
// task to notify change, otherwise, a system level hidden permission
// INTERACT_ACROSS_USERS_FULL is needed.
// The related APIs were added in API 17, it should be safe to fallback to
// normal way for notifying change, because caller can't be other users in
// devices whose API level is less than API 17.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
UserHandle callingUserHandle = Binder.getCallingUserHandle();
if (callingUserHandle != null
&& !callingUserHandle.equals(android.os.Process.myUserHandle())) {
ThreadUtils.postOnUiThread(new Runnable() {
@Override
public void run() {
getContext().getContentResolver().notifyChange(uri, null);
}
});
return;
}
}
getContext().getContentResolver().notifyChange(uri, null);
}
/**
* Determines whether or not the {@link RecognizerIntent#ACTION_WEB_SEARCH} {@link Intent}
* is handled by any {@link android.app.Activity}s in the system. The result will be cached for
* future calls. Passing {@code false} to {@code useCachedValue} will force it to re-query any
* {@link android.app.Activity}s that can process the {@link Intent}.
* @param context The {@link Context} to use to check to see if the {@link Intent} will
* be handled.
* @param useCachedValue Whether or not to use the cached value from a previous result.
* @return {@code true} if recognition is supported. {@code false} otherwise.
*/
public static boolean isRecognitionIntentPresent(Context context, boolean useCachedValue) {
ThreadUtils.assertOnUiThread();
if (sHasRecognitionIntentHandler == null || !useCachedValue) {
PackageManager pm = context.getPackageManager();
List<ResolveInfo> activities = pm.queryIntentActivities(
new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
sHasRecognitionIntentHandler = activities.size() > 0;
}
return sHasRecognitionIntentHandler;
}
public static DataReductionProxySettings getInstance() {
ThreadUtils.assertOnUiThread();
if (sSettings == null) {
sSettings = new DataReductionProxySettings();
}
return sSettings;
}
private void postCallbackResult() {
if (mCallback == null) return;
ThreadUtils.postOnUiThread(new Runnable() {
@Override
public void run() {
mCallback.onResult(get());
}
});
}
private boolean requestPostMessageChannelInternal(final CustomTabsSessionToken session,
final Uri postMessageOrigin) {
if (!mWarmupHasBeenCalled.get()) return false;
if (!isCallerForegroundOrSelf() && !CustomTabActivity.isActiveSession(session)) {
return false;
}
if (!mClientManager.bindToPostMessageServiceForSession(session)) return false;
final int uid = Binder.getCallingUid();
ThreadUtils.postOnUiThread(new Runnable() {
@Override
public void run() {
// If the API is not enabled, we don't set the post message origin, which will
// avoid PostMessageHandler initialization and disallow postMessage calls.
if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_POST_MESSAGE_API)) return;
// Attempt to verify origin synchronously. If successful directly initialize
// postMessage channel for session.
Uri verifiedOrigin = verifyOriginForSession(session, uid, postMessageOrigin);
if (verifiedOrigin == null) {
mClientManager.verifyAndInitializeWithPostMessageOriginForSession(
session, postMessageOrigin);
} else {
mClientManager.initializeWithPostMessageOriginForSession(
session, verifiedOrigin);
}
}
});
return true;
}
/**
* Called from native when template URL service is done loading.
*/
@CalledByNative
private void templateUrlServiceLoaded() {
ThreadUtils.assertOnUiThread();
for (LoadListener listener : mLoadListeners) {
listener.onTemplateUrlServiceLoaded();
}
}
/**
* Create a new asynchronous request to select a client certificate.
*
* @param nativePtr The native object responsible for this request.
* @param window A WindowAndroid instance.
* @param keyTypes The list of supported key exchange types.
* @param encodedPrincipals The list of CA DistinguishedNames.
* @param hostName The server host name is available (empty otherwise).
* @param port The server port if available (0 otherwise).
* @return true on success.
* Note that nativeOnSystemRequestComplete will be called iff this method returns true.
*/
@CalledByNative
private static boolean selectClientCertificate(final long nativePtr, final WindowAndroid window,
final String[] keyTypes, byte[][] encodedPrincipals, final String hostName,
final int port) {
ThreadUtils.assertOnUiThread();
final Activity activity = window.getActivity().get();
if (activity == null) {
Log.w(TAG, "Certificate request on GC'd activity.");
return false;
}
// Build the list of principals from encoded versions.
Principal[] principals = null;
if (encodedPrincipals.length > 0) {
principals = new X500Principal[encodedPrincipals.length];
try {
for (int n = 0; n < encodedPrincipals.length; n++) {
principals[n] = new X500Principal(encodedPrincipals[n]);
}
} catch (Exception e) {
Log.w(TAG, "Exception while decoding issuers list: " + e);
return false;
}
}
KeyChainCertSelectionCallback callback =
new KeyChainCertSelectionCallback(activity.getApplicationContext(),
nativePtr);
KeyChainCertSelectionWrapper keyChain = new KeyChainCertSelectionWrapper(activity,
callback, keyTypes, principals, hostName, port, null);
maybeShowCertSelection(keyChain, callback,
new CertSelectionFailureDialog(activity));
// We've taken ownership of the native ssl request object.
return true;
}
/**
* Returns a singleton instance of the settings object.
*
* Needs the native library to be loaded, otherwise it will crash.
*/
public static DataReductionProxySettings getInstance() {
ThreadUtils.assertOnUiThread();
if (sSettings == null) {
sSettings = new DataReductionProxySettings();
}
return sSettings;
}
public static void initNetworkChangeNotifier(Context context) {
ThreadUtils.assertOnUiThread();
TraceEvent.begin("NetworkChangeNotifier.init");
// Enable auto-detection of network connectivity state changes.
NetworkChangeNotifier.init(context);
NetworkChangeNotifier.setAutoDetectConnectivityState(true);
TraceEvent.end("NetworkChangeNotifier.init");
}
/**
* Sets a callback that will be executed when the initialization is done.
*
* @param callback This is called when the initialization is done.
* @param timeoutMs If initializing takes more than this time since this function is called,
* force run |callback| early. The unit is ms.
*/
public static void setOnInitializeAsyncFinished(final Runnable callback, long timeoutMs) {
sInitializeAsyncCallbacks.add(callback);
ThreadUtils.postOnUiThreadDelayed(
new Runnable() {
@Override
public void run() {
if (sInitializeAsyncCallbacks.remove(callback)) callback.run();
}
},
sIsInitialized ? 0 : timeoutMs);
}
@CalledByNative
public void showPrintDialog() {
ThreadUtils.assertOnUiThread();
if (mController != null) { // The native side doesn't check if printing is enabled
mController.startPendingPrint(this);
} else {
Log.d(TAG, "Unable to start printing, feature not available.");
// Printing disabled. Notify the native side to stop waiting.
showSystemDialogDone();
}
}
private static InputStream getInputStream(final AwContentsClient contentClient)
throws IOException {
final PipedInputStream inputStream = new PipedInputStream();
final PipedOutputStream outputStream = new PipedOutputStream(inputStream);
// Send the request to UI thread to callback to the client, and if it provides a
// valid bitmap bounce on to the worker thread pool to compress it into the piped
// input/output stream.
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
final Bitmap defaultVideoPoster = contentClient.getDefaultVideoPoster();
if (defaultVideoPoster == null) {
closeOutputStream(outputStream);
return;
}
AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
@Override
public void run() {
try {
defaultVideoPoster.compress(Bitmap.CompressFormat.PNG, 100,
outputStream);
outputStream.flush();
} catch (IOException e) {
Log.e(TAG, null, e);
} finally {
closeOutputStream(outputStream);
}
}
});
}
});
return inputStream;
}
/**
* High confidence mayLaunchUrl() call, that is:
* - Tries to prerender if possible.
* - An empty URL cancels the current prerender if any.
* - If prerendering is not possible, makes sure that there is a spare renderer.
*/
private void highConfidenceMayLaunchUrl(CustomTabsSessionToken session,
int uid, String url, Bundle extras, List<Bundle> otherLikelyBundles) {
ThreadUtils.assertOnUiThread();
if (TextUtils.isEmpty(url)) {
cancelPrerender(session);
return;
}
WarmupManager warmupManager = WarmupManager.getInstance();
Profile profile = Profile.getLastUsedProfile();
url = DataReductionProxySettings.getInstance().maybeRewriteWebliteUrl(url);
int debugOverrideValue = NO_OVERRIDE;
if (extras != null) debugOverrideValue = extras.getInt(DEBUG_OVERRIDE_KEY, NO_OVERRIDE);
boolean didStartPrerender = false, didStartPrefetch = false;
boolean mayPrerender = mayPrerender(session);
if (mayPrerender) {
if (debugOverrideValue == PREFETCH_ONLY) {
didStartPrefetch = new ResourcePrefetchPredictor(profile).startPrefetching(url);
if (didStartPrefetch) mSpeculation = SpeculationParams.forPrefetch(session, url);
} else if (debugOverrideValue != NO_PRERENDERING) {
didStartPrerender = prerenderUrl(session, url, extras, uid);
}
}
preconnectUrls(otherLikelyBundles);
if (!didStartPrefetch) warmupManager.maybePreconnectUrlAndSubResources(profile, url);
if (!didStartPrerender) warmupManager.createSpareWebContents();
}
/**
* Unbind a high priority process which was previous bound with bindAsHighPriority.
* @param pid The process handle of the service.
*/
void unbindAsHighPriority(final int pid) {
final ChildProcessConnection connection = sServiceMap.get(pid);
if (connection == null) {
LogPidWarning(pid, "Tried to unbind non-existent connection");
return;
}
if (!connection.isStrongBindingBound()) return;
// This runnable performs the actual unbinding. It will be executed synchronously when
// on low-end devices and posted with a delay otherwise.
Runnable doUnbind = new Runnable() {
@Override
public void run() {
synchronized (mCountLock) {
if (connection.isStrongBindingBound()) {
decrementOomCount(pid);
connection.detachAsActive();
}
}
}
};
if (SysUtils.isLowEndDevice()) {
doUnbind.run();
} else {
ThreadUtils.postOnUiThreadDelayed(doUnbind, DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS);
}
}
/**
* Register an |observer| to observe system accounts seeding status.
*/
public void addSystemAccountsSeededListener(OnSystemAccountsSeededListener observer) {
ThreadUtils.assertOnUiThread();
mSystemAccountsSeedingObservers.addObserver(observer);
if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_DONE) {
observer.onSystemAccountsSeedingComplete();
}
}
/**
* Retrieve the singleton instance of this class.
*
* @param context the current context.
* @return the singleton instance.
*/
public static SyncController get(Context context) {
ThreadUtils.assertOnUiThread();
if (sInstance == null) {
sInstance = new SyncController(context.getApplicationContext());
}
return sInstance;
}
public List<CreditCard> getCreditCards() {
ThreadUtils.assertOnUiThread();
int count = nativeGetCreditCardCount(mPersonalDataManagerAndroid);
List<CreditCard> cards = new ArrayList<CreditCard>(count);
for (int i = 0; i < count; i++) {
cards.add(nativeGetCreditCardByIndex(mPersonalDataManagerAndroid, i));
}
return cards;
}
/**
* Start listening for location updates until we're told to quit. May be
* called in any thread.
* @param gpsEnabled Whether or not we're interested in high accuracy GPS.
*/
@CalledByNative
public boolean start(final boolean gpsEnabled) {
FutureTask<Void> task = new FutureTask<Void>(new Runnable() {
@Override
public void run() {
mImpl.start(gpsEnabled);
}
}, null);
ThreadUtils.runOnUiThread(task);
return true;
}
/**
* If precaching is enabled, then allow the PrecacheController to be launched and signal Chrome
* when conditions are right to start precaching. If precaching is disabled, prevent the
* PrecacheController from ever starting.
*
* @param context any context within the application
*/
@VisibleForTesting
void updateEnabled(final Context context) {
Log.v(TAG, "updateEnabled starting");
ThreadUtils.postOnUiThread(new Runnable() {
@Override
public void run() {
mCalled = true;
final ProfileSyncService sync = ProfileSyncService.get();
if (mListener == null && sync != null) {
mListener = new ProfileSyncService.SyncStateChangedListener() {
public void syncStateChanged() {
if (sync.isBackendInitialized()) {
mSyncInitialized = true;
updateEnabledSync(context);
}
}
};
sync.addSyncStateChangedListener(mListener);
}
if (mListener != null) {
// Call the listener once, in case the sync backend is already initialized.
mListener.syncStateChanged();
}
Log.v(TAG, "updateEnabled complete");
}
});
}
/**
* Called by native to retrieve OAuth2 tokens.
*
* @param username The native username (full address).
* @param scope The scope to get an auth token for (without Android-style 'oauth2:' prefix).
* @param nativeCallback The pointer to the native callback that should be run upon completion.
*/
@CalledByNative
public static void getOAuth2AuthToken(
Context context, String username, String scope, final long nativeCallback) {
Account account = getAccountOrNullFromUsername(context, username);
if (account == null) {
ThreadUtils.postOnUiThread(new Runnable() {
@Override
public void run() {
nativeOAuth2TokenFetched(null, false, nativeCallback);
}
});
return;
}
String oauth2Scope = OAUTH2_SCOPE_PREFIX + scope;
AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(context);
accountManagerHelper.getAuthToken(
account, oauth2Scope, new AccountManagerHelper.GetAuthTokenCallback() {
@Override
public void tokenAvailable(String token) {
nativeOAuth2TokenFetched(token, false, nativeCallback);
}
@Override
public void tokenUnavailable(boolean isTransientError) {
nativeOAuth2TokenFetched(null, isTransientError, nativeCallback);
}
});
}
/**
* Returns the singleton instance of HelpAndFeedback, creating it if needed.
*/
@SuppressFBWarnings("LI_LAZY_INIT_STATIC")
public static HelpAndFeedback getInstance(Context context) {
ThreadUtils.assertOnUiThread();
if (sInstance == null) {
sInstance = ((ChromeApplication) context.getApplicationContext())
.createHelpAndFeedback();
}
return sInstance;
}