@Override
  protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    String[] parameters = getIntent().getStringArrayExtra(EXTRAS);
    if (parameters != null) {
      for (String s : parameters) {
        s = s.replace("\\,", ",");
      }
    }
    if (Intent.ACTION_VIEW.equals(getIntent().getAction())) {
      Uri uri = getIntent().getData();
      if (uri != null) {
        Log.i(TAG, "MojoShellActivity opening " + uri);
        if (parameters == null) {
          parameters = new String[] {uri.toString()};
        } else {
          String[] newParameters = new String[parameters.length + 1];
          System.arraycopy(parameters, 0, newParameters, 0, parameters.length);
          newParameters[parameters.length] = uri.toString();
          parameters = newParameters;
        }
      }
    }

    // TODO(ppi): Gotcha - the call below will work only once per process lifetime, but the OS
    // has no obligation to kill the application process between destroying and restarting the
    // activity. If the application process is kept alive, initialization parameters sent with
    // the intent will be stale.
    // TODO(qsr): We should be passing application context here as required by
    // InitApplicationContext on the native side. Currently we can't, as PlatformViewportAndroid
    // relies on this being the activity context.
    ShellMain.ensureInitialized(this, parameters);
    ShellMain.start();
  }
 @Override
 @SuppressFBWarnings("DM_EXIT")
 public void onDestroy() {
   Log.i(TAG, "Destroying ChildProcessService pid=%d", Process.myPid());
   super.onDestroy();
   if (mActivitySemaphore.tryAcquire()) {
     // TODO(crbug.com/457406): This is a bit hacky, but there is no known better solution
     // as this service will get reused (at least if not sandboxed).
     // In fact, we might really want to always exit() from onDestroy(), not just from
     // the early return here.
     System.exit(0);
     return;
   }
   synchronized (mMainThread) {
     try {
       while (!mLibraryInitialized) {
         // Avoid a potential race in calling through to native code before the library
         // has loaded.
         mMainThread.wait();
       }
     } catch (InterruptedException e) {
       // Ignore
     }
   }
   // Try to shutdown the MainThread gracefully, but it might not
   // have chance to exit normally.
   nativeShutdownMainThread();
 }
Beispiel #3
0
 /**
  * Installs secondary dexes if possible.
  *
  * <p>Isolated processes (e.g. renderer processes) can't load secondary dex files on K and below,
  * so we don't even try in that case.
  *
  * @param context The application context.
  */
 @VisibleForTesting
 public static void install(Context context) {
   try {
     // TODO(jbudorick): Back out this version check once support for K & below works.
     // http://crbug.com/512357
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && processIsIsolated()) {
       Log.i(TAG, "Skipping multidex installation: inside isolated process.");
     } else {
       MultiDex.install(context);
       Log.i(TAG, "Completed multidex installation.");
     }
   } catch (NoSuchMethodException e) {
     Log.wtf(TAG, "Failed multidex installation", e);
   } catch (IllegalAccessException e) {
     Log.wtf(TAG, "Failed multidex installation", e);
   } catch (InvocationTargetException e) {
     Log.wtf(TAG, "Failed multidex installation", e);
   }
 }
Beispiel #4
0
  /**
   * * Creates a BluetoothAdapterWrapper using the default android.bluetooth.BluetoothAdapter. May
   * fail if the default adapter is not available or if the application does not have sufficient
   * permissions.
   */
  @CalledByNative
  public static BluetoothAdapterWrapper createWithDefaultAdapter(Context context) {
    final boolean hasPermissions =
        context.checkCallingOrSelfPermission(Manifest.permission.BLUETOOTH)
                == PackageManager.PERMISSION_GRANTED
            && context.checkCallingOrSelfPermission(Manifest.permission.BLUETOOTH_ADMIN)
                == PackageManager.PERMISSION_GRANTED;
    if (!hasPermissions) {
      Log.w(TAG, "BluetoothAdapterWrapper.create failed: Lacking Bluetooth permissions.");
      return null;
    }

    BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    if (adapter == null) {
      Log.i(TAG, "BluetoothAdapterWrapper.create failed: Default adapter not found.");
      return null;
    } else {
      Log.i(TAG, "BluetoothAdapterWrapper created with default adapter.");
      return new BluetoothAdapterWrapper(adapter);
    }
  }
  @Override
  public Boolean call() {
    Log.i(TAG, "Trying to extract logcat for minidump");
    try {
      // Step 1: Extract a single logcat file.
      File logcatFile = getElidedLogcat();

      // Step 2: Make copies of logcat file for each  minidump then invoke
      // MinidumpPreparationService on each file pair.
      int len = mMinidumpFilenames.length;
      CrashFileManager fileManager = new CrashFileManager(mContext.getCacheDir());
      for (int i = 0; i < len; i++) {
        // Output crash dump file path to logcat so non-browser crashes appear too.
        Log.i(TAG, "Output crash dump:");
        Log.i(TAG, fileManager.getCrashFile(mMinidumpFilenames[i]).getAbsolutePath());
        processMinidump(logcatFile, mMinidumpFilenames[i], fileManager, i == len - 1);
      }
      return true;
    } catch (IOException | InterruptedException e) {
      Log.w(TAG, e.toString());
      return false;
    }
  }
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    if (item == mDeleteButton) {
      // Log added for detecting delete button double clicking.
      Log.i(TAG, "Delete button pressed by user! isFinishing() == " + isFinishing());

      mEnhancedBookmarksModel.deleteBookmark(mBookmarkId);
      finish();
      return true;
    } else if (item.getItemId() == android.R.id.home) {
      finish();
      return true;
    }
    return super.onOptionsItemSelected(item);
  }
 /**
  * Returns true if the Background Sync Manager should be automatically disabled on startup. This
  * is currently only the case if Play Services is not up to date, since any sync attempts which
  * fail cannot be reregistered. Better to wait until Play Services is updated before attempting
  * them.
  *
  * @param context The application context.
  */
 @CalledByNative
 private static boolean shouldDisableBackgroundSync(Context context) {
   // Check to see if Play Services is up to date, and disable GCM if not.
   // This will not automatically set {@link sGCMEnabled} to true, in case it has been
   // disabled in tests.
   if (sGCMEnabled) {
     if (!canUseGooglePlayServices(context)) {
       setGCMEnabled(false);
       Log.i(TAG, "Disabling Background Sync because Play Services is not up to date.");
       recordBooleanHistogram("BackgroundSync.LaunchTask.PlayServicesAvailable", false);
     } else {
       recordBooleanHistogram("BackgroundSync.LaunchTask.PlayServicesAvailable", true);
     }
   }
   return !sGCMEnabled;
 }
  private void runTest(final String fileName, final String fileNameExpected)
      throws FileNotFoundException, IOException, InterruptedException, TimeoutException {
    loadUrlWebViewAsync("file://" + fileName, mTestActivity);

    if (getInstrumentation().isRebaseline()) {
      // this is the rebaseline process
      mTestActivity.waitForFinish(TIMEOUT_SECONDS, TimeUnit.SECONDS);
      String result = mTestActivity.getTestResult();
      writeFile(fileNameExpected, result, true);
      Log.i(TAG, "file: " + fileNameExpected + " --> rebaselined, length=" + result.length());
    } else {
      String expected = readFile(fileNameExpected);
      mTestActivity.waitForFinish(TIMEOUT_SECONDS, TimeUnit.SECONDS);
      String result = mTestActivity.getTestResult();
      assertEquals(expected, result);
    }
  }
  private static ChromiumLinkerParams getLinkerParamsForNewConnection() {
    if (!sLinkerInitialized) {
      if (Linker.isUsed()) {
        sLinkerLoadAddress = Linker.getBaseLoadAddress();
        if (sLinkerLoadAddress == 0) {
          Log.i(TAG, "Shared RELRO support disabled!");
        }
      }
      sLinkerInitialized = true;
    }

    if (sLinkerLoadAddress == 0) return null;

    // Always wait for the shared RELROs in service processes.
    final boolean waitForSharedRelros = true;
    return new ChromiumLinkerParams(
        sLinkerLoadAddress, waitForSharedRelros, Linker.getTestRunnerClassName());
  }
Beispiel #10
0
  @Override
  public void renderProcessGone(boolean processWasOomProtected) {
    Log.i(
        TAG,
        "renderProcessGone() for tab id: "
            + mTab.getId()
            + ", oom protected: "
            + Boolean.toString(processWasOomProtected)
            + ", already needs reload: "
            + Boolean.toString(mTab.needsReload()));
    // Do nothing for subsequent calls that happen while the tab remains crashed. This
    // can occur when the tab is in the background and it shares the renderer with other
    // tabs. After the renderer crashes, the WebContents of its tabs are still around
    // and they still share the RenderProcessHost. When one of the tabs reloads spawning
    // a new renderer for the shared RenderProcessHost and the new renderer crashes
    // again, all tabs sharing this renderer will be notified about the crash (including
    // potential background tabs that did not reload yet).
    if (mTab.needsReload() || mTab.isShowingSadTab()) return;

    // This will replace TabRendererCrashStatus if numbers line up.
    int appState = ApplicationStatus.getStateForApplication();
    boolean applicationRunning = (appState == ApplicationState.HAS_RUNNING_ACTIVITIES);
    boolean applicationPaused = (appState == ApplicationState.HAS_PAUSED_ACTIVITIES);
    @TabRendererExitStatus int rendererExitStatus = TAB_RENDERER_EXIT_STATUS_MAX;
    if (processWasOomProtected) {
      if (applicationRunning) {
        rendererExitStatus = TAB_RENDERER_EXIT_STATUS_OOM_PROTECTED_IN_RUNNING_APP;
      } else if (applicationPaused) {
        rendererExitStatus = TAB_RENDERER_EXIT_STATUS_OOM_PROTECTED_IN_PAUSED_APP;
      } else {
        rendererExitStatus = TAB_RENDERER_EXIT_STATUS_OOM_PROTECTED_IN_BACKGROUND_APP;
      }
    } else {
      if (applicationRunning) {
        rendererExitStatus = TAB_RENDERER_EXIT_STATUS_NOT_PROTECTED_IN_RUNNING_APP;
      } else if (applicationPaused) {
        rendererExitStatus = TAB_RENDERER_EXIT_STATUS_NOT_PROTECTED_IN_PAUSED_APP;
      } else {
        rendererExitStatus = TAB_RENDERER_EXIT_STATUS_NOT_PROTECTED_IN_BACKGROUND_APP;
      }
    }
    RecordHistogram.recordEnumeratedHistogram(
        "Tab.RendererExitStatus", rendererExitStatus, TAB_RENDERER_EXIT_STATUS_MAX);

    int activityState =
        ApplicationStatus.getStateForActivity(mTab.getWindowAndroid().getActivity().get());
    int rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_MAX;
    if (!processWasOomProtected
        || activityState == ActivityState.PAUSED
        || activityState == ActivityState.STOPPED
        || activityState == ActivityState.DESTROYED) {
      // The tab crashed in background or was killed by the OS out-of-memory killer.
      // setNeedsReload(true);
      mTab.setNeedsReload(true);
      if (applicationRunning) {
        rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_HIDDEN_IN_FOREGROUND_APP;
      } else {
        rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_HIDDEN_IN_BACKGROUND_APP;
      }
    } else {
      rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_SHOWN_IN_FOREGROUND_APP;
      mTab.showSadTab();
      // This is necessary to correlate histogram data with stability counts.
      UmaSessionStats.logRendererCrash();
    }
    RecordHistogram.recordEnumeratedHistogram(
        "Tab.RendererCrashStatus", rendererCrashStatus, TAB_RENDERER_CRASH_STATUS_MAX);

    mTab.handleTabCrash();

    boolean sadTabShown = mTab.isShowingSadTab();
    RewindableIterator<TabObserver> observers = mTab.getTabObservers();
    while (observers.hasNext()) {
      observers.next().onCrash(mTab, sadTabShown);
    }
  }
Beispiel #11
0
    @Override
    public void onImageAvailable(ImageReader reader) {
      synchronized (mCaptureStateLock) {
        if (mCaptureState != CaptureState.STARTED) {
          Log.e(TAG, "Get captured frame in unexpected state.");
          return;
        }
      }

      // If device is rotated, inform native, then re-create ImageReader and VirtualDisplay
      // with the new orientation, and drop the current frame.
      if (maybeDoRotation()) {
        createImageReaderWithFormat();
        createVirtualDisplay();
        return;
      }

      try (Image image = reader.acquireLatestImage()) {
        if (image == null) return;
        if (reader.getWidth() != image.getWidth() || reader.getHeight() != image.getHeight()) {
          Log.e(
              TAG,
              "ImageReader size ("
                  + reader.getWidth()
                  + "x"
                  + reader.getHeight()
                  + ") did not match Image size ("
                  + image.getWidth()
                  + "x"
                  + image.getHeight()
                  + ")");
          throw new IllegalStateException();
        }

        switch (image.getFormat()) {
          case PixelFormat.RGBA_8888:
            if (image.getPlanes().length != 1) {
              Log.e(
                  TAG, "Unexpected image planes for RGBA_8888 format: " + image.getPlanes().length);
              throw new IllegalStateException();
            }

            nativeOnRGBAFrameAvailable(
                mNativeScreenCaptureMachineAndroid,
                image.getPlanes()[0].getBuffer(),
                image.getPlanes()[0].getRowStride(),
                image.getCropRect().left,
                image.getCropRect().top,
                image.getCropRect().width(),
                image.getCropRect().height(),
                image.getTimestamp());
            break;
          case ImageFormat.YUV_420_888:
            if (image.getPlanes().length != 3) {
              Log.e(
                  TAG,
                  "Unexpected image planes for YUV_420_888 format: " + image.getPlanes().length);
              throw new IllegalStateException();
            }

            // The pixel stride of Y plane is always 1. The U/V planes are guaranteed
            // to have the same row stride and pixel stride.
            nativeOnI420FrameAvailable(
                mNativeScreenCaptureMachineAndroid,
                image.getPlanes()[0].getBuffer(),
                image.getPlanes()[0].getRowStride(),
                image.getPlanes()[1].getBuffer(),
                image.getPlanes()[2].getBuffer(),
                image.getPlanes()[1].getRowStride(),
                image.getPlanes()[1].getPixelStride(),
                image.getCropRect().left,
                image.getCropRect().top,
                image.getCropRect().width(),
                image.getCropRect().height(),
                image.getTimestamp());
            break;
          default:
            Log.e(TAG, "Unexpected image format: " + image.getFormat());
            throw new IllegalStateException();
        }
      } catch (IllegalStateException ex) {
        Log.e(TAG, "acquireLatestImage():" + ex);
      } catch (UnsupportedOperationException ex) {
        Log.i(TAG, "acquireLatestImage():" + ex);
        // YUV_420_888 is the preference, but not all devices support it,
        // fall-back to RGBA_8888 then.
        mFormat = PixelFormat.RGBA_8888;
        createImageReaderWithFormat();
        createVirtualDisplay();
      }
    }
  @Override
  public void onCreate() {
    Log.i(TAG, "Creating new ChildProcessService pid=%d", Process.myPid());
    if (sContext.get() != null) {
      throw new RuntimeException("Illegal child process reuse.");
    }
    sContext.set(this);
    super.onCreate();

    mMainThread =
        new Thread(
            new Runnable() {
              @Override
              @SuppressFBWarnings("DM_EXIT")
              public void run() {
                try {
                  // CommandLine must be initialized before others, e.g., Linker.isUsed()
                  // may check the command line options.
                  synchronized (mMainThread) {
                    while (mCommandLineParams == null) {
                      mMainThread.wait();
                    }
                  }
                  CommandLine.init(mCommandLineParams);
                  Linker linker = Linker.getInstance();
                  boolean useLinker = linker.isUsed();
                  boolean requestedSharedRelro = false;
                  if (useLinker) {
                    synchronized (mMainThread) {
                      while (!mIsBound) {
                        mMainThread.wait();
                      }
                    }
                    assert mLinkerParams != null;
                    if (mLinkerParams.mWaitForSharedRelro) {
                      requestedSharedRelro = true;
                      linker.initServiceProcess(mLinkerParams.mBaseLoadAddress);
                    } else {
                      linker.disableSharedRelros();
                    }
                    linker.setTestRunnerClassName(mLinkerParams.mTestRunnerClassName);
                  }
                  boolean isLoaded = false;
                  if (CommandLine.getInstance()
                      .hasSwitch(BaseSwitches.RENDERER_WAIT_FOR_JAVA_DEBUGGER)) {
                    android.os.Debug.waitForDebugger();
                  }

                  boolean loadAtFixedAddressFailed = false;
                  try {
                    LibraryLoader.get(LibraryProcessType.PROCESS_CHILD)
                        .loadNow(getApplicationContext());
                    isLoaded = true;
                  } catch (ProcessInitException e) {
                    if (requestedSharedRelro) {
                      Log.w(
                          TAG,
                          "Failed to load native library with shared RELRO, " + "retrying without");
                      loadAtFixedAddressFailed = true;
                    } else {
                      Log.e(TAG, "Failed to load native library", e);
                    }
                  }
                  if (!isLoaded && requestedSharedRelro) {
                    linker.disableSharedRelros();
                    try {
                      LibraryLoader.get(LibraryProcessType.PROCESS_CHILD)
                          .loadNow(getApplicationContext());
                      isLoaded = true;
                    } catch (ProcessInitException e) {
                      Log.e(TAG, "Failed to load native library on retry", e);
                    }
                  }
                  if (!isLoaded) {
                    System.exit(-1);
                  }
                  LibraryLoader.get(LibraryProcessType.PROCESS_CHILD)
                      .registerRendererProcessHistogram(
                          requestedSharedRelro, loadAtFixedAddressFailed);
                  LibraryLoader.get(LibraryProcessType.PROCESS_CHILD).initialize();
                  synchronized (mMainThread) {
                    mLibraryInitialized = true;
                    mMainThread.notifyAll();
                    while (mFdInfos == null) {
                      mMainThread.wait();
                    }
                  }
                  ContentMain.initApplicationContext(sContext.get().getApplicationContext());
                  for (FileDescriptorInfo fdInfo : mFdInfos) {
                    nativeRegisterGlobalFileDescriptor(
                        fdInfo.mId, fdInfo.mFd.detachFd(), fdInfo.mOffset, fdInfo.mSize);
                  }
                  nativeInitChildProcess(
                      sContext.get().getApplicationContext(),
                      ChildProcessService.this,
                      mCpuCount,
                      mCpuFeatures);
                  if (mActivitySemaphore.tryAcquire()) {
                    ContentMain.start();
                    nativeExitChildProcess();
                  }
                } catch (InterruptedException e) {
                  Log.w(TAG, "%s startup failed: %s", MAIN_THREAD_NAME, e);
                } catch (ProcessInitException e) {
                  Log.w(TAG, "%s startup failed: %s", MAIN_THREAD_NAME, e);
                }
              }
            },
            MAIN_THREAD_NAME);
    mMainThread.start();
  }